Szukaj…


Uwagi

Ustawiać

Przed użyciem powiązania danych musisz włączyć wtyczkę w swoim build.gradle .

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

Uwaga: Powiązanie danych zostało dodane do wtyczki Android Gradle w wersji 1.5.0

Wiążące nazwy klas

Wtyczka powiązania danych generuje nazwę klasy powiązania, konwertując nazwę pliku układu na wielkość liter Pascala i dodając „Binding” na końcu. Zatem item_detail_activity.xml wygeneruje klasę o nazwie ItemDetailActivityBinding .

Zasoby

Podstawowe wiązanie pól tekstowych

Konfiguracja Gradle (moduł: aplikacja)

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

Model danych

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

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

Układ XML

Pierwszym krokiem jest zawinięcie układu w znacznik <layout> , dodanie elementu <data> i dodanie elementu <variable> do modelu danych.

Następnie możesz powiązać atrybuty XML z polami w modelu danych za pomocą @{model.fieldname} , gdzie model to nazwa zmiennej, a nazwa fieldname to pole, do którego chcesz uzyskać dostęp.

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>

Dla każdego pliku układu XML poprawnie skonfigurowanego z powiązaniami wtyczka Android Gradle generuje odpowiednią klasę: powiązania. Ponieważ mamy układ o nazwie item_detail_activity , odpowiednia wygenerowana klasa wiązania nazywa się ItemDetailActivityBinding .

Wiązanie to można następnie wykorzystać w działaniu takim jak:

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

Wiązanie metodą akcesorium

Jeśli twój model ma prywatne metody, biblioteka wiązania danych nadal umożliwia dostęp do nich w twoim widoku bez używania pełnej nazwy metody.

Model danych

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

Układ 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>

Odwoływanie się do klas

Model danych

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

Układ XML

Musisz zaimportować klasy, do których istnieją odniesienia, tak jak w Javie.

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

Uwaga: Pakiet java.lang.* Jest importowany automatycznie przez system. (To samo robi JVM dla Java )

Wiązanie danych we fragmencie

Model danych

public class Item {
    private String name;

    public String getName() {
        return name;
    }

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

}

Układ 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>

Fragment

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

Wbudowane dwukierunkowe wiązanie danych

Dwukierunkowe wiązanie danych obsługuje następujące atrybuty:

Element Nieruchomości
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

Stosowanie

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

Zauważ, że wyrażenie Binding @={} ma dodatkowe = , które jest niezbędne do dwukierunkowego Binding . Nie można używać metod w dwukierunkowych wyrażeniach wiążących.

Powiązanie danych w adapterze RecyclerView

Możliwe jest również użycie powiązania danych w ramach adaptera RecyclerView .

Model danych

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

Układ XML

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

Klasa adaptera

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

Kliknij nasłuchiwanie z wiązaniem

Utwórz interfejs dla ClickHandler

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

Układ 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>

Obsługuj wydarzenie w swojej działalności

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

Zdarzenie niestandardowe przy użyciu wyrażenia lambda

Zdefiniuj interfejs

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

Utwórz klasę modelu

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

Układ 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>

Kod działania:

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

W przypadku niektórych programów nasłuchujących widoku, które nie są dostępne w kodzie XML, ale można je ustawić w kodzie Java, można je powiązać z niestandardowym wiązaniem.

Klasa niestandardowa

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

Klasa obsługi

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>

Wartość domyślna w powiązaniu danych

Okienko podglądu wyświetla wartości domyślne dla wyrażeń powiązania danych, jeśli są podane.

Na przykład :

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

Podczas projektowania zajmie wrap_content i będzie działał jako wrap_content w okienku podglądu.

Innym przykładem jest

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

Wyświetli Preview Text w okienku podglądu, ale po uruchomieniu go w urządzeniu / emulatorze zostanie wyświetlony powiązany z nim tekst

Wiązanie danych ze zmiennymi niestandardowymi (int, boolean)

Czasami musimy wykonać podstawowe operacje, takie jak ukrywanie / pokazywanie widoku w oparciu o jedną wartość, dla tej jednej zmiennej nie możemy stworzyć modelu lub nie jest dobrą praktyką tworzenie modelu dla tego. DataBinding obsługuje podstawowe typy danych do wykonywania tych operacji.

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

i ustaw jego wartość z klasy java.

binding.setSelected(true);

Wiązanie danych w oknie dialogowym

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

Przekaż widget jako odniesienie w BindingAdapter

Układ 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>

Metoda 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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow