Suche…


Bemerkungen

Konfiguration

Bevor Sie die Datenbindung verwenden, müssen Sie das Plugin in Ihrem build.gradle .

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

Hinweis: Die Datenbindung wurde dem Android Gradle-Plugin in Version 1.5.0 hinzugefügt

Verbindliche Klassennamen

Das Datenbindungs-Plugin generiert einen Bindungsklassennamen, indem der Dateiname Ihres Layouts in Pascal-Fall konvertiert und am Ende "Binding" hinzugefügt wird. Somit generiert item_detail_activity.xml eine Klasse mit dem Namen ItemDetailActivityBinding .

Ressourcen

Grundlegende Textfeldbindung

Gradle (Modul: App) Konfiguration

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

Datenmodell

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

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

Layout XML

Der erste Schritt besteht darin, Ihr Layout in ein <layout> -Tag einzuhüllen, ein <data> -Element hinzuzufügen und ein <variable> -Element für Ihr Datenmodell hinzuzufügen.

Anschließend können Sie XML-Attribute mit @{model.fieldname} an Felder im Datenmodell @{model.fieldname} , wobei model der Name der Variablen und fieldname das Feld ist, auf das Sie zugreifen möchten.

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>

Für jede XML-Layoutdatei, die ordnungsgemäß mit Bindungen konfiguriert ist, generiert das Android Gradle-Plugin eine entsprechende Klasse: Bindungen. Da wir ein Layout mit dem Namen item_detail_activity haben , heißt die entsprechende generierte Bindungsklasse ItemDetailActivityBinding .

Diese Bindung kann dann in einer Aktivität verwendet werden:

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

Binden mit einer Accessor-Methode

Wenn Ihr Modell über private Methoden verfügt, können Sie in der Datenbindungsbibliothek immer noch auf diese zugreifen, ohne den vollständigen Namen der Methode zu verwenden.

Datenmodell

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

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

Klassen referenzieren

Datenmodell

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

Layout XML

Sie müssen referenzierte Klassen genauso importieren wie in 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>

Hinweis: Das Paket java.lang.* Wird automatisch vom System importiert. (Das gleiche wird von JVM für Java )

Datenbindung in Fragment

Datenmodell

public class Item {
    private String name;

    public String getName() {
        return name;
    }

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

}

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

Integrierte bidirektionale Datenbindung

Die bidirektionale Datenbindung unterstützt die folgenden Attribute:

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

Verwendungszweck

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

Beachten Sie, dass der Bindungsausdruck @={} ein zusätzliches = , das für die bidirektionale Bindung erforderlich ist. Methoden können nicht in bidirektionalen Bindungsausdrücken verwendet werden.

Datenbindung im RecyclerView Adapter

Es ist auch möglich, die Datenbindung in Ihrem RecyclerView Adapter zu verwenden.

Datenmodell

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

XML-Layout

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

Adapterklasse

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

Klicken Sie auf Listener mit Bindung

Erstellen Sie eine Schnittstelle für clickHandler

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

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

Ereignis in Ihrer Aktivität behandeln

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

Benutzerdefiniertes Ereignis mit Lambda-Ausdruck

Schnittstelle definieren

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

Erstellen Sie eine Modellklasse

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

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

Aktivitätscode:

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

Für einige Ansichtslistener, die nicht im XML-Code verfügbar sind, aber im Java-Code festgelegt werden können, kann sie mit benutzerdefinierten Bindungen gebunden werden.

Benutzerdefinierte Klasse

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

Handler-Klasse

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>

Standardwert in Datenbindung

Der Vorschaufenster zeigt Standardwerte für Datenbindungsausdrücke an, sofern angegeben.

Zum Beispiel :

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

Es wrap_content während des Entwurfs wrap_content und wrap_content im Vorschaufenster als wrap_content .

Ein anderes Beispiel ist

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

Es wird Preview Text im Vorschaufenster angezeigt. Wenn Sie ihn jedoch im Gerät / Emulator ausführen, wird der tatsächlich an ihn gebundene Text angezeigt

DataBinding mit benutzerdefinierten Variablen (int, boolean)

Manchmal müssen wir grundlegende Vorgänge ausführen, wie zum Beispiel die Ansicht verbergen / anzeigen, die auf einem einzelnen Wert basiert. Für diese einzelne Variable können wir kein Modell erstellen, oder es ist nicht ratsam, ein Modell dafür zu erstellen. DataBinding unterstützt grundlegende Datentypen, um diese Operationen auszuführen.

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

und seinen Wert von der Java-Klasse festlegen.

binding.setSelected(true);

Datenbindung im Dialog

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

Übergeben Sie das Widget als Referenz in BindingAdapter

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

@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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow