Поиск…


замечания

Настроить

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

android {
    ....
    dataBinding {
        enabled = true
    }
}

Примечание: привязка данных была добавлена ​​в плагин Android Gradle версии 1.5.0

Названия классов привязки

Плагин привязки данных генерирует имя класса привязки путем преобразования имени файла макета в файл Pascal и добавления «Связывание» до конца. Таким образом item_detail_activity.xml будет генерировать класс с именем ItemDetailActivityBinding .

Ресурсы

Связывание основного текстового поля

Конфигурация Gradle (Module: app)

android {
    ....
    dataBinding {
        enabled = true
    }
}

Модель данных

public class Item {
    public String name;
    public String description;

    public Item(String name, String description) {
        this.name = name;
        this.description = description;
    }
}

Макет XML

Первым шагом является перенос вашего макета в <layout> , добавление элемента <data> и добавление элемента <variable> для вашей модели данных.

Затем вы можете привязать атрибуты XML к полям в модели данных, используя @{model.fieldname} , где model - это имя переменной, а fieldname - поле, к которому вы хотите получить доступ.

item_detail_activity.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="item" type="com.example.Item"/>
   </data>

   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{item.name}"/>

       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{item.description}"/>

   </LinearLayout>
</layout>

Для каждого файла макета XML, правильно настроенного с привязками, плагин Android Gradle генерирует соответствующий класс: привязки. Поскольку у нас есть макет с именем item_detail_activity , соответствующий сгенерированный класс привязки называется ItemDetailActivityBinding .

Затем это связывание можно использовать в Деятельности, например:

public class ItemDetailActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       ItemDetailActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.item_detail_activity);
       Item item = new Item("Example item", "This is an example item.");
       binding.setItem(item);
    }
}

Связывание с методом доступа

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

Модель данных

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

Макет XML

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="item" type="com.example.Item"/>
   </data>

   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

       <!-- Since the "name" field is private on our data model,
            this binding will utilize the public getName() method instead. -->
       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{item.name}"/>

   </LinearLayout>
</layout>

Ссылки на классы

Модель данных

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

Макет XML

Вы должны импортировать ссылочные классы, как и в Java.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <import type="android.view.View"/>
       <variable name="item" type="com.example.Item"/>
   </data>

   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

       <!-- We reference the View class to set the visibility of this TextView -->
       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{item.name}"
           android:visibility="@{item.name == null ? View.VISIBLE : View.GONE"/>

   </LinearLayout>
</layout>

Примечание . Пакет java.lang.* Автоматически импортируется системой. (То же самое делает JVM для Java )

Сопоставление данных в фрагменте

Модель данных

public class Item {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name){
        this.name = name;
    }

}

Макет XML

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="item" type="com.example.Item"/>
   </data>

   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{item.name}"/>

   </LinearLayout>
</layout>

Фрагмент

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    FragmentTest binding = DataBindingUtil.inflate(inflater, R.layout.fragment_test, container, false);
    Item item = new Item();
    item.setName("Thomas");
    binding.setItem(item);
    return binding.getRoot();
}

Встроенная двусторонняя привязка данных

Двусторонняя привязка данных поддерживает следующие атрибуты:

Элемент свойства
AbsListView android:selectedItemPosition
CalendarView android:date
CompoundButton android:checked
DatePicker
  • android:year
  • android:month
  • android:day
EditText android:text
NumberPicker android:value
RadioGroup android:checkedButton
RatingBar android:rating
SeekBar android:progress
TabHost android:currentTab
TextView android:text
TimePicker
  • android:hour
  • android:minute
ToggleButton android:checked
Switch android:checked

использование

<layout ...>
    <data>
        <variable type="com.example.myapp.User" name="user"/>
    </data>
    <RelativeLayout ...>
        <EditText android:text="@={user.firstName}" .../>
    </RelativeLayout>
</layout>

Обратите внимание, что выражение Binding @={} имеет дополнительный = , что необходимо для двухстороннего связывания . Невозможно использовать методы в двухсторонних выражениях привязки.

Связывание данных в адаптере RecyclerView

Также возможно использовать привязку данных в вашем адаптере RecyclerView .

Модель данных

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

XML-макет

<TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@{item.name}"/>

Класс адаптера

public class ListItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private Activity host;
    private List<Item> items;

    public ListItemAdapter(Activity activity, List<Item> items) {
        this.host = activity;
        this.items = items;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // inflate layout and retrieve binding
        ListItemBinding binding = DataBindingUtil.inflate(host.getLayoutInflater(),
                R.layout.list_item, parent, false);

        return new ItemViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        Item item = items.get(position);

        ItemViewHolder itemViewHolder = (ItemViewHolder)holder;
        itemViewHolder.bindItem(item);
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    private static class ItemViewHolder extends RecyclerView.ViewHolder {
        ListItemBinding binding;

        ItemViewHolder(ListItemBinding binding) {
            super(binding.getRoot());
            this.binding = binding;
        }

        void bindItem(Item item) {
            binding.setItem(item);
            binding.executePendingBindings();
        }
    }
}

Нажмите прослушиватель с привязкой

Создать интерфейс для clickHandler

public interface ClickHandler {
    public void onButtonClick(View v);
}

Макет XML

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="handler"
            type="com.example.ClickHandler"/>
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="click me"
            android:onClick="@{handler.onButtonClick}"/>
    </RelativeLayout>
</layout>

Обработка события в вашей деятельности

public class MainActivity extends Activity implements ClickHandler {

    private ActivityMainBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        binding.setHandler(this);
    }

    @Override
    public void onButtonClick(View v) {
        Toast.makeText(context,"Button clicked",Toast.LENGTH_LONG).show();
    }
}

Пользовательское событие с использованием выражения лямбда

Определить интерфейс

public interface ClickHandler {
    public void onButtonClick(User user);
}

Создать класс модели

public class User {
    private String name;

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Макет XML

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="handler"
            type="com.example.ClickHandler"/>

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

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}"
            android:onClick="@{() -> handler.onButtonClick(user)}"/>
    </RelativeLayout>
</layout>

Код мероприятия:

public class MainActivity extends Activity implements ClickHandler {

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

    @Override
    public void onButtonClick(User user) {
        Toast.makeText(MainActivity.this,"Welcome " + user.getName(),Toast.LENGTH_LONG).show();
    }
}

Для некоторого слушателя, который недоступен в коде xml, но может быть установлен в java-коде, его можно связать с пользовательской привязкой.

Пользовательский класс

public class BindingUtil {
    @BindingAdapter({"bind:autoAdapter"})
    public static void setAdapter(AutoCompleteTextView view, ArrayAdapter<String> pArrayAdapter) {
        view.setAdapter(pArrayAdapter);
    }
    @BindingAdapter({"bind:onKeyListener"})
    public static void setOnKeyListener(AutoCompleteTextView view , View.OnKeyListener pOnKeyListener)
    {
        view.setOnKeyListener(pOnKeyListener);
    }
}

Класс обработчика

public class Handler extends BaseObservable {
    private ArrayAdapter<String> roleAdapter;
       
    public ArrayAdapter<String> getRoleAdapter() {
        return roleAdapter;
    }
    public void setRoleAdapter(ArrayAdapter<String> pRoleAdapter) {
        roleAdapter = pRoleAdapter;
    }
}

XML

<layout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bind="http://schemas.android.com/tools" >

    <data>
        <variable
            name="handler"
            type="com.example.Handler" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <AutoCompleteTextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:singleLine="true"
            bind:autoAdapter="@{handler.roleAdapter}" />

    </LinearLayout>
</layout>

Значение по умолчанию в привязке данных

На панели «Предварительный просмотр» отображаются значения по умолчанию для выражений привязки данных, если они предоставлены.

Например :

android:layout_height="@{@dimen/main_layout_height, default=wrap_content}"

Это займет wrap_content при проектировании и будет действовать как wrap_content в области предварительного просмотра.

Другим примером является

android:text="@{user.name, default=`Preview Text`}"

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

DataBinding с пользовательскими переменными (int, boolean)

Иногда нам нужно выполнять основные операции, такие как hide / show view, основанные на одном значении, для этой единственной переменной мы не можем создать модель, или это не очень хорошая практика для создания модели для этого. DataBinding поддерживает базовые типы данных для выполнения этих отпечатков.

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <import type="android.view.View" />

        <variable
            name="selected"
            type="Boolean" />

    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World"
            android:visibility="@{selected ? View.VISIBLE : View.GONE}" />

    </RelativeLayout>
</layout>

и установить его значение из класса java.

binding.setSelected(true);

Связывание данных в диалоге

public void doSomething() {
    DialogTestBinding binding = DataBindingUtil
            .inflate(LayoutInflater.from(context), R.layout.dialog_test, null, false);

    Dialog dialog = new Dialog(context);
    dialog.setContentView(binding.getRoot());
    dialog.show();
}

Пропустить виджет в качестве ссылки в BindingAdapter

Макет XML

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
   
   </data>

   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

       <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

        <ImageView
        android:id="@+id/img"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        app:imageUrl="@{url}"
        app:progressbar="@{progressBar}"/>

   </LinearLayout>
</layout>

Метод BindingAdapter

@BindingAdapter({"imageUrl","progressbar"})
public static void loadImage(ImageView view, String imageUrl, ProgressBar progressBar){
    Glide.with(view.getContext()).load(imageUrl)
                        .listener(new RequestListener<String, GlideDrawable>() {
                    @Override
                    public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
                        return false;
                    }

                    @Override
                    public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                        progressBar.setVisibility(View.GONE);
                        return false;
                    }
                }).into(view);
}


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow