Buscar..


Observaciones

Preparar

Antes de utilizar el enlace de datos, debe habilitar el complemento en su build.gradle .

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

Nota: el enlace de datos se agregó al complemento Gradle de Android en la versión 1.5.0

Encuadernación de nombres de clase

El complemento de enlace de datos genera un nombre de clase de enlace al convertir el nombre de archivo de su diseño al caso de Pascal y agregar "Enlace" al final. Por item_detail_activity.xml tanto, item_detail_activity.xml generará una clase llamada ItemDetailActivityBinding .

Recursos

Enlace de campo de texto básico

Configuración de Gradle (Módulo: aplicación)

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

Modelo de datos

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

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

Diseño XML

El primer paso es envolver su diseño en una etiqueta <layout> , agregar un elemento <data> y agregar un elemento <variable> para su modelo de datos.

A continuación, puede obligar a los atributos XML a campos en el modelo de datos utilizando @{model.fieldname} , donde model es el nombre de la variable y el fieldname es el campo al que desea acceder.

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>

Para cada archivo de diseño XML correctamente configurado con enlaces, el complemento Gradle de Android genera una clase correspondiente: enlaces. Debido a que tenemos un diseño denominado item_detail_activity , la clase de enlace generada correspondiente se llama ItemDetailActivityBinding .

Este enlace puede ser utilizado en una actividad como esta:

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

Encuadernación con un método de acceso.

Si su modelo tiene métodos privados, la biblioteca de enlace de datos todavía le permite acceder a ellos en su vista sin usar el nombre completo del método.

Modelo de datos

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

Diseño 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>

Clases de referencia

Modelo de datos

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

Diseño XML

Debe importar las clases referenciadas, tal como lo haría en 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>

Nota: el paquete importa java.lang.* Automáticamente. (Lo mismo está hecho por JVM para Java )

Encuadernación de datos en Fragmento

Modelo de datos

public class Item {
    private String name;

    public String getName() {
        return name;
    }

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

}

Diseño 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>

Fragmento

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

Enlace de datos bidireccional incorporado

El enlace de datos bidireccional admite los siguientes atributos:

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

Uso

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

Observe que la expresión de enlace @={} tiene un = adicional , que es necesario para el enlace de dos vías . No es posible utilizar métodos en expresiones de enlace de dos vías.

Enlace de datos en el adaptador RecyclerView

También es posible utilizar el enlace de datos dentro de su adaptador RecyclerView .

Modelo de datos

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

Diseño XML

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

Clase de adaptador

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

Click listener con Binding

Crear interfaz para clickHandler

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

Diseño 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>

Manejar evento en tu actividad.

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

Evento personalizado usando la expresión lambda

Definir interfaz

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

Crear clase de modelo

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

Diseño 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>

Código de actividad:

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

Para algunos oyentes de vista que no están disponibles en el código xml, pero se pueden configurar en código java, se pueden enlazar con enlaces personalizados.

Clase personalizada

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

Clase de manejador

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>

Valor por defecto en enlace de datos

El panel de vista previa muestra los valores predeterminados para las expresiones de enlace de datos, si se proporcionan.

Por ejemplo :

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

Tomará wrap_content durante el diseño y actuará como wrap_content en el panel de vista previa.

Otro ejemplo es

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

Mostrará Preview Text en el panel de vista previa, pero cuando lo ejecute en el dispositivo / emulador, se mostrará el texto real vinculado a él.

Enlace de datos con variables personalizadas (int, booleano)

A veces necesitamos realizar operaciones básicas como la vista de ocultar / mostrar basada en un solo valor, para esa única variable no podemos crear un modelo o no es una buena práctica crear un modelo para eso. DataBinding admite tipos de datos básicos para realizar esas operaciones.

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

y establecer su valor de clase 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();
}

Pase el widget como referencia en BindingAdapter

Diseño 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>

Método 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
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow