DataBinding使用

参考【Android】DataBinding库(MVVM设计模式)

入门

在module的build.gradle配置:

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

Bean对象

public class User {

    private String name;
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

布局

content_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="user"
            type="com.yolo.myapplication.User" />
    </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="@{user.name}" />
    </RelativeLayout>
</layout>

注意:这里跟平时的布局有点不同。需要在原布局基础上包装一层layout节点,并在自己的同级增加data节点。

data:声明了需要用到的对象,type用于指定对象路径,name是对此对象重新命名,方便使用属性。

可以在TextView中的看到android:text=”@{user.name}”。

绑定数据

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);

    ContentMainBinding binding = DataBindingUtil.setContentView(this, R.layout.content_main);
    User user = new User();
    user.setName("我是名字");
    binding.setUserBean(user);
}
  1. 生成的DataBinding名与绑定的布局名称保持一致的。即假如布局是R.layout.activity_main,那么类名就ActivityMainBinding。

  2. 布局中variable节点下的name值影响着binding的方法名。即如果布局中name值是userBean,那么binding的方法名就是setUserBean。

  3. 如果是include的布局,则需要执行具体的layout资源。

<!-- activity_main.xml  包含了content_main,如果需要绑定content_main的UI,则应该制定此布局-->
<include
        layout="@layout/content_main"/>

扩展

命名

修改DataBinding名,只需在data节点下增加class属性即可。

<data class="ContentBinding">
    <variable
        name="user"
        type="com.yolo.myapplication.User" />
</data>

导包

type的值还可以使用导包的形式

<data class="ContentBinding">
    <import type="com.yolo.myapplication.User"/>
    <variable
        name="user"
        type="User" />
</data>

遇到相同的类名, 可以取别名

<data>
      <import type="com.example.gavin.databindingtest.User" alias="User"/>
      <import type="com.example.gavin.mc.User" alias="mcUser"/>
      <variable name="user" type="User"/>
      <variable name="mcUser" type="mcUser"/>
</data>

用到的对象也需要导包

<data>
      <import type="android.view.View"/>
</data>
...
<TextView
    ...
    android:visibility="@{user.isStudent ? View.VISIBLE : View.GONE}"
/>

表达式

  • 形式1:
<TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="@{userBean.girl?View.VISIBLE:View.GONE}" />
  • 形式2
    注意:外层的双引号需要改成单引号
<TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{userBean.girl?"Girl": "Other"}' />

运算符??

除了常用的操作法,另外还提供了一个 null 的合并运算符号 ??,这是一个三目运算符的简便写法。

contact.lastName ?? contact.name

相当于

contact.lastName != null ? contact.lastName : contact.name

绑定图片

绑定图片与绑定文本略有不同,前者需要使用BindingAdapter注解,声明一个属性。

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

    <data class="ContentBinding">
        <variable
            name="imgUrl"
            type="String" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:scaleType="centerCrop"
            app:image="@{imgUrl}" />
    </RelativeLayout>
</layout>

定义显示图片的静态方法【必须是静态方法

@BindingAdapter("image")
public static void showImage(ImageView iv, String url){
    Glide.with(iv.getContext()).load(url).into(iv);
}

如果不是静态方法,则抛如下异常

Caused by: java.lang.IllegalStateException: Required DataBindingComponent is null in class ContentBinding. 

A BindingAdapter in com.yolo.myapplication.MainActivity is not static and requires an object to use, retrieved from the DataBindingComponent. 

If you don't use an inflation method taking a DataBindingComponent, use DataBindingUtil.setDefaultComponent or make all BindingAdapter methods static.

绑定,设置Url地址即可

binding.setImgUrl("http://image.uczzd.cn/14094444771339725257.png?id=0");

点击事件

布局

<data class="ContentBinding">
    <variable
        name="handle"
        type="com.yolo.myapplication.MainActivity" />
</data>

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="登录"
        android:onClick="@{handle.login}"/>

响应事件

 //参数View必须有,必须是public,参数View不能改成对应的控件,只能是View,否则编译不通过
  public void login(View view) {
      Toast.makeText(this, "登录", Toast.LENGTH_LONG).show();
  }

绑定

//1.响应事件在Activity中
binding.setHandle(this);
//2.响应事件在其他类中,传递类的对象
binding.setHandle(new Other());

//待续


版权声明:本文为Jason847原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。