Использование библиотеки DataBinding для привязки событий

Я пытаюсь связать события с представлениями в XML, используя DataBinding Library, поставляемую с Android M. Я следую примерам из Разработчики Android и поэтапное внедрение. для атрибутов представления, таких как видимость, текст, он работает нормально, но если я попытаюсь выполнить привязку с помощью onclick, он не будет работать должным образом. Вот пример кода, который я пробовал до сих пор:

 <data>
    <import type="android.view.View"/>
    <variable name="user" type="com.example.databinding.User"/>
    <variable name="handlers" type="com.example.databinding.MyHandlers"/>
</data>

 <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{user.firstName}"
    android:visibility="@{user.isFriend ? View.VISIBLE : View.GONE}" />
 <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Click Me"
    android:id="@+id/button"
    android:layout_gravity="left"
    android:onClick="@{handlers.onClickFriend}"/>

Основная деятельность :

  public class MainActivity extends AppCompatActivity {

  User user;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityMainBinding binding = 
    DataBindingUtil.setContentView(this,R.layout.activity_main);
    user = new User("Pankaj","Kumar",true,true);
    binding.setUser(user);
   }
 }

Мои обработчики:

public class MyHandlers {
public void onClickFriend(View view){
    Log.i(MyHandlers.class.getSimpleName(),"Now Friend");
}

public void onClickEnemy(View view){
    Log.i(MyHandlers.class.getSimpleName(),"Now Enemy");
  }
}

Я написал только необходимый код для улучшения читабельности. Может ли кто-нибудь помочь мне в этом.


person Pankaj    schedule 12.08.2015    source источник


Ответы (9)


Я думаю, вам нужно будет также связать handlers, может быть, что-то вроде этого в onCreate:

MyHandlers handlers = new MyHandlers();
binding.setHandlers(handlers);
person justHooman    schedule 12.08.2015
comment
Да, и если вы используете свой класс Activity в качестве обработчиков, вам просто нужно сделать это: binding.setHandlers(this); - person dorsz; 20.07.2016
comment
Если у вас много одинаковых действий, вы можете использовать эту библиотеку для простоты — github.com/drstranges/ActionHandler - person Roman_D; 17.08.2016
comment
@dorsz +100 тебе! Я искал это часами! - person kirtan403; 10.09.2016
comment
то же самое касается докладчиков, если вы используете докладчиков - person Abdul Samad; 03.01.2017
comment
Как настроить сенсорный прослушиватель с помощью привязки данных? - person chetan; 11.01.2017
comment
@chetan, насколько я понимаю, я думаю, что нет способа настроить сенсорный прослушиватель с использованием привязки данных по умолчанию, потому что он не поддерживается в xml, но если вы используете его много раз, вы можете написать собственное представление с пользовательским атрибутом onTouch в xml и использовать привязка данных к этому представлению. - person justHooman; 12.01.2017
comment
Отлично! Я бы хотел, чтобы в документации это было описано лучше! Спасибо за отличный ответ! - person BlackHatSamurai; 23.01.2017
comment
Правильно, большое спасибо. - person Pankaj Kant Patel; 24.02.2017

Много способов настройки клика

  1. Передать обработчик в привязку.

    Привязка ActivityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main); Обработчик Hander = новый Handler(); привязка.setHandler(обработчик);

  2. Установить клики (используйте любой из ниже)

    android:onClick=@{handler::onClickMethodReference}

OR

android:onClick="@{handler.onClickMethodReference}"

OR

android:onClick="@{() -> handler.onClickLamda()}"

OR

android:onClick="@{(v) -> handler.onClickLamdaWithView(v)}"

OR

android:onClick="@{() -> handler.onClickLamdaWithView(model)}"

См. класс Handler для понимания.

public class Handler {
    public void onClickMethodReference(View view) {
        //
    }
    public void onClickLamda() {
        //
    }
    public void onClickLamdaWithView(View view) {
        //
    }
    public void onClickLamdaWithObject(Model model) {
        //
    }
}

Обратите внимание, что

  • Вы можете использовать справочник по методу (::), если у вас есть тот же аргумент, что и у атрибута onClick.
  • Вы можете передать любой объект, например onClickLamdaWithObject.
  • Если вам нужно передать объект View, просто используйте выражение (v)->.

Дополнительная литература

https://developer.android.com/topic/libraries/data-binding/expressions

person Khemraj Sharma    schedule 17.08.2018
comment
Это отличный ответ. Обратите внимание, что только нижние три со стрелкой являются единственными, которые позволяют вам перейти к коду в вашем обработчике из xml (по состоянию на март 19) - person Gober; 20.03.2019

Используйте этот формат в своем xml:

android:onClick="@{handlers::onClickFriend}"

Обратите внимание на ::, не беспокойтесь о красных линиях в редакторе xml, потому что в настоящее время он открыт ошибка для xml-редактора Android Studio.

Где handlers — ваша переменная из тега данных:

<data>
    <variable name="handlers" type="com.example.databinding.MyHandlers"/>
</data>

и onClickFriend - ваш метод:

public class MyHandlers {
    public void onClickFriend(View view) {
        Log.i(MyHandlers.class.getSimpleName(),"Now Friend");
    }
}

ДОБАВЛЕНО

Для дескриптора onLongClick в xml добавьте следующее:

android:onLongClick="@{handlers::onLongClickFriend}"

и добавьте метод onLongClickFriend в свой класс ViewModel:

public class MyHandlers {
    public boolean onLongClickFriend(View view) {
        Log.i(MyHandlers.class.getSimpleName(),"Long clicked Friend");
        return true;
    }
}

ДОБАВЛЕНО

Если вам нужно показать всплывающее сообщение, вы можете использовать интерфейс (лучший вариант) или передать context в классе MyHandlers в конструкции:

public class MyHandlers {
    public boolean onLongClickFriend(View view) {
        Toast.makeText(view.getContext(), "On Long Click Listener", Toast.LENGTH_SHORT).show();
        return true;
    }
}
person walkmn    schedule 07.11.2016
comment
Привет, ты знаешь, как обрабатывать события onlongclick? - person Mussa; 01.12.2016
comment
Это не сработало. Не удалось скомпилировать проект. Unknown attribute android:onLongClick. - person Mussa; 01.12.2016
comment
Извините, попробуйте изменить void на boolean в методе следующим образом: public boolean onLongClickFriend(View view) и добавить return true; в конце. - person walkmn; 01.12.2016
comment
@walkmn, как показать тост или передать контекст в методе onClickFriend - person YLS; 19.12.2016
comment
мы можем использовать метод view.getContext(), чтобы получить context внутри каждого метода, поэтому нет необходимости передавать его с помощью конструктора. - person cgb_pandey; 02.06.2021

Если вы собираетесь использовать свою активность, можете также заменить объект context, который автоматически привязывается, иначе вы тратите место впустую.

Специальная переменная с именем context генерируется для использования в выражениях привязки по мере необходимости. Значение для контекста — это контекст из getContext() корневого представления. Контекстная переменная будет переопределена явным объявлением переменной с таким именем.

binding.setContext(this);

и

<variable name="context" type="com.example.MyActivity"/>

Обратите внимание, что если вы просто используете простую строку onClick="someFunc", это вообще не функция привязки данных. Это более старая функция, которая использует небольшое отражение, чтобы найти метод в контексте.

person androidguy    schedule 19.09.2016

Ты должен сделать

android:onClick="@{() -> handlers.onClickFriend()}"
person Mladen Rakonjac    schedule 03.09.2017
comment
Вы имеете в виду android:onClick="@{(view) -> handlers.onClickFriend}", иначе эта лямбда не соответствовала бы сигнатуре события onClick. - person AymenDaoudi; 14.11.2017
comment
@AymenDaoudi правильнее должно быть android:onClick="@{(view) -> handlers.onClickFriend()}" - person Oleksii Masnyi; 05.06.2018
comment
Единственный метод, который сработал для меня, от @AlekseyMasny. Спасибо! - person Alexander Haroldo da Rocha; 12.06.2018
comment
Синтаксис () -> function() вполне допустим. Ознакомьтесь с документацией: developer.android.com/topic/libraries/data. -привязка/ - person dominicoder; 09.07.2020

Я публикую это только для того, чтобы охватить оба способа достижения этого. 1. по привязке слушателя 2. по ссылке на метод

макет:

<layout...>
<data>

        <variable
            name="handlers"
            type="com.example.databinding.MyPresenter" />
        <variable name="user" type="com.example.databinding.User"/>
</data>

<LinearLayout
  android:layout_width="wrap_content"
  android:layout_height="wrap_content">

    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="32dp"
            android:text="Using Listener Binding"
            android:onClick="@{() -> handlers.onLisClick(user)}"/>

     <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="32dp"
            android:text="Using Method Ref"
            android:onClick="@{handlers::onButtonClicked}"/>            

</LinearLayout>
</layout>

Мероприятия:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding =
                DataBindingUtil.setContentView(this, R.layout.activity_main);
        MyPresenter presenter = new MyPresenter();
        User user = new User("Alex","RJ")
        binding.setUser(user);
        binding.setHandlers(presenter);
    }

Мой ведущий:

public class MyPresenter{

//using listener binding
public void onLisClick(User user){
//do something..
}


//using method reference
public void onButtonClicked(View view){

// do something
}

}

Примечание:
1. При использовании ссылки на метод сигнатура метода должна быть такой же, как и для любого другого метода onClick, т. е. общедоступного и параметра View as.

2. При использовании привязки прослушивателя у вас есть преимущество, заключающееся в том, что вы можете напрямую передать объект, если хотите, и выполнить любую операцию.

person Man    schedule 27.06.2018

Не обязательно создавать отдельный класс MyHandlers и вызывать setHandlers для обработки android:onClick. Вы можете просто использовать методы: public void onClickFriend(View view) и public void onClickEnemy(View view) в MainActivity. Вид активности:

public class MainActivity extends AppCompatActivity {
    User user;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding =
                DataBindingUtil.setContentView(this, R.layout.activity_main);
        user = new User("Pankaj", "Kumar", true, true);
        binding.setUser(user);
    }

    public void onClickFriend(View view) {
        Log.i(MyHandlers.class.getSimpleName(), "Now Friend");
    }

    public void onClickEnemy(View view) {
        Log.i(MyHandlers.class.getSimpleName(), "Now Enemy");
    }
}

Макет:

<data>
    <import type="android.view.View"/>
    <variable name="user" type="com.example.databinding.User"/>
</data>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{user.firstName}"
    android:visibility="@{user.isFriend ? View.VISIBLE : View.GONE}" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Click Me"
    android:id="@+id/button"
    android:layout_gravity="left"
    android:onClick="@{onClickFriend}"/>

Взгляните на пример использования библиотеки привязки данных для шаблона MVVM: http://cases.azoft.com/mvvm-android-data-binding

person Vladimir Tchernitski    schedule 18.12.2015
comment
ну android:onClick="@{onClickFriend}" не работало, а android:onClick="onClickFriend" работало как обычно.. - person Bharatesh; 27.04.2016
comment
Это почти правда. Вы можете использовать свою активность в качестве обработчиков, а onClick в макете похож на android:onClick="@{handlers::onClickFriend}", но вам нужно привязать обработчики в действии, например: binding.setHandlers(this); - person dorsz; 20.07.2016
comment
Привет, ты знаешь, как обрабатывать события onlongclick? - person Mussa; 01.12.2016

Я публикую это, потому что у меня была другая ситуация, в которой это произошло. Если у вас есть два действия, ссылающиеся на файл макета, и одно определяет событие onclick, а другое не дает вам того же предупреждения и, как ни странно, в действии, где вы определили событие.

Чтобы проверить это, я рекомендую найти использование файла макета по right clicking в имени макета и нажать find references. Не забудьте восстановить послесловие приложения.

person jobbert    schedule 09.05.2018

Для тех, у кого возникают проблемы с обработкой событий с длинным кликом:

Сначала создайте представление в макете с идентификатором.

<data>
        <variable
            name="tempDesc"
            type="String" />
        <variable
            name="activity"
            type="com.naruto.trangoapp.MainActivity" />
</data>

<TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{(view) -> activity.changeDescText(view)}"
            android:text="@{tempDesc}" />

В вашем методе onCreate используйте идентификатор представления для установки любого прослушивателя: -

binding.textView.setOnLongClickListener(this::onLongClick);

затем просто создайте логический метод с тем же именем, т. е. onLongClick, например:

private boolean onLongClick(View l) {
        Toast.makeText(this, "Description", Toast.LENGTH_SHORT).show();
        return true;
    }

Это все!!

Примечание. Вы также можете установить любой метод для любого представления в макете, установив контекст для переменной активности в методе onCreate:

binding.setActivity(this);

Затем определите и передайте имя метода с представлением в макете, чтобы использовать его в файле Activity. Например, я использовал метод changeDescText (v) с именем переменной «активность» для моего Textview. Вот мой метод в файле активности: -

public void changeDescText(View view) {
        binding.setTempDesc("Description Changed");
    }
person Aman Kumar    schedule 21.03.2020
comment
Не храните ссылку на активность в привязке данных, иначе вы получите утечку памяти. - person TheLibrarian; 11.06.2020
comment
@TheLibrarian У вас есть источник на этот счет? - person Florian Walther; 10.07.2020