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


Я пытаюсь связать события с представлениями в xml, используя библиотеку привязки данных , поставляемую с 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);
   }
 }

MyHandlers:

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");
  }
}

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

8 30

8 ответов:

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

MyHandlers handlers = new MyHandlers();
binding.setHandlers(handlers);

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

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

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

Где handlers - переменная из тега data:

<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 {

    private Context context;

    public MyHandlers(Context context) {
        this.context = context;
    }

    public boolean onLongClickFriend(View view) {
        Toast.makeText(context, "On Long Click Listener", Toast.LENGTH_SHORT).show();
        return true;
    }
}

Не обязательно создавать отдельный класс 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

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

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

binding.setContext(this);

И

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

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

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

android:onClick="@{() -> handlers.onClickFriend()}"

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

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

Множество способов установить клики

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

ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
Hander handler = new Handler();
binding.setHandlers(handlers);

2) установить клики (используйте любой из приведенных ниже)

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

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

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

Расположение:

<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);
    }

MyPresenter:

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, т. е. public и View as parameter.

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