В этом уроке рассмотрим как обрабатывать события View.

 

С помощью биндинга мы можем вешать обработчики на события View. Есть два способа это сделать, давайте рассмотрим их. 

 

 

 

Ссылка на метод

Рассмотрим пример с onClick. Допустим, у нас на экране, который отображает данные по работнику (Employee), есть кнопка Delete и мы хотим присвоить ей onClick обработчик.

 

Создаем свой класс обработчик:

public class MyHandler  {

   public void onDelete(View view) {
       // ...
   }

}

Он не обязательно должен наследовать OnClickListener. Но его метод должен быть public и иметь те же параметры, что и метод OnClickListener.onClick(View view), т.е. должен быть один параметр типа View. Имя метода может быть любым.

 

Прописываем этот обработчик, как variable в layout.

<data>
   <variable
       name="handler"
       type="ru.startandroid.application.MyHandler" />
  
   ...

</data>

 

В onClick кнопки ссылаемся на его метод onDelete:

<Button
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@string/delete"
   android:onClick="@{handler::onDelete}"/>

 

Осталось создать объект MyHandler и передать его в биндинг:

MyHandler myHandler = new MyHandler();
binding.setHandler(myHandler);

 

По нажатию на кнопку Delete будет вызван метод onDelete объекта myHandler.

 

Если при попытке настроить обработчик в биндинге вы получаете подобную ошибку:

Listener class android.view.View.OnClickListener with method onClick did not match signature of any method handler::onDelete

внимательно проверьте, что модификаторы доступа и параметры метода в вашем обработчике такие же, что и в методе интерфейса стандартного обработчика. В случае с onClick - это OnClickListener.

 

 

 

Вызов метода 

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

 

Рассмотрим снова пример с onClick. Создаем обработчик.

public class MyHandler  {

   public void onDelete(Employee employee) {
       // ...
   }

}

В метод onDelete мы планируем получать не View, как в примере раньше, а объект Employee.

 

MyHandler так же, как и ранее, прописываем в variable и передаем в binding.

 

В onClick кнопки пишем вызов

<Button
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@string/delete"
   android:onClick="@{(view) -> handler.onDelete(employee)}"/>

Здесь используетcя лямбда. На вход нам предлагаются те же параметры, что и в методе интерфейса стандартного обработчика, т.е. view из OnClickListener.onClick(View view). Но мы не используем этот параметр. В метод onDelete мы передаем employee, который у нас описан, как один из variable в layout.

 

В результате по нажатию на кнопку, биндинг предоставит нам View, на которое было нажатие. Но мы его проигнорируем, возьмем у биндинга объект Employee и отправим в handler.onDelete.

 

Биндинг дает нам возможность не писать параметры в лямбде, если они нам не нужны. Т.е. можно сделать так:

<Button
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@string/delete"
   android:onClick="@{() -> handler.onDelete(employee)}"/>

Таким образом биндинг поймет, что его View нам не нужно, и не будет его передавать. Имейте ввиду, что если в стандартном обработчике несколько параметров, то вы можете указать либо все параметры, либо ни одного.

 

 

 

Чтобы закрепить тему, давайте рассмотрим пример с CheckBox. Например, на экране с данными по работнику есть чекбокс Enabled, который включает/выключает работника.


В обработчике создаем метод,

public class MyHandler  {

   public void onEnabled(Employee employee, boolean enabled) {
       // ...
   }

}

Будем получать объект Employee и состояние чекбокса.

 

В onCheckedChanged пишем вызов метода нашего обработчика.

<CheckBox
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@string/enabled"
   android:onCheckedChanged="@{(view, checked) -> handler.onEnabled(employee, checked)}" />

В лямбде указываем параметры, которые пришли бы нам в стандартном обработчике OnCheckedChangeListener.onCheckedChanged(CompoundButton compoundButton, boolean checked).

Параметр view нам не понадобится, а вот checked передаем в метод вместе с employee.

 

Теперь по нажатию на чекбокс, биндинг будет вызывать метод onEnabled и передавать туда Employee объект и состояние чекбокса.

 

 

 

Рассмотрим еще несколько интересных моментов.

 

При вызове обработчика мы можем использовать условия.

Например, есть такой обработчик.

public class MyHandler  {

   public void onEnabled(Employee employee) {
       // ...
   }

   public void onDisabled(Employee employee) {
       // ...
   }

}

 

Мы можем в layout указать его методы следующим образом

<CheckBox
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@string/enabled"
   android:onCheckedChanged="@{(view, checked) -> checked ? handler.onEnabled(employee) : handler.onDisabled(employee)}"/>

Т.е. если чекбокс включен, то вызываем метод onEnabled, иначе - onDisabled.

 

Если в одном из случаев нам ничего не надо вызывать, то можно использовать void

<CheckBox
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@string/enabled"
   android:onCheckedChanged="@{(view, checked) -> checked ? handler.onEnabled(employee) : void}"/>

 

 

В биндиге по умолчанию есть переменная context, которую вы всегда можете использовать, если есть необходимость.

<CheckBox
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@string/enabled"
   android:onCheckedChanged="@{(view, checked) -> handler.onEnabled(employee, checked, context)}"/>

Значение переменной context получено вызовом метода getContext у корневого View вашего layout.

 

 

В этих примерах я создавал отдельный объект обработчика, но разумеется вы можете создавать интерфейсы. прописывать их в качестве variable в layout и использовать хоть само Activity в качестве реализации.


Language

Социальные сети

 

Telegram канал



Android чат в Telegram



Группа ВКонтакте



Страница в Facebook