Android DataBinding使用详解

一、简介

在Google I/O 2015上,伴随着 Android M 预览版发布了DataBinding兼容函数库。DataBinding可以帮开发者节省大量无脑力代码,包括findViewById(),setText(),setOnClick()等。

二、使用步骤

1、Gradle中添加支持DataBinding

在build.gradle的android下添加如下代码:

dataBinding{
    enabled true
}

这样项目就支持了DataBinding的功能。

2、定义实体类

代码如下:

public class UserInfo{
    private String name;
    private int age;
    private boolean isStudent;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }

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

    public boolean isStudent() {
        return isStudent;
    }

    public void setStudent(boolean student) {
        isStudent = student;
    }

    public UserInfo(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public UserInfo(String name, int age, boolean isStudent) {
        this.name = name;
        this.age = age;
        this.isStudent = isStudent;
    }
}

3、布局文件xml中定义

xml中根节点是layout,在layout中有两个子节点。第一部分是data节点,第二部分是我们之前布局文件。data节点用于定义变量,在data节点定义一个variable,变量的名称用name指定,变量的类型用type指定。第二个节点和我们以前的布局文件一样。代码如下:

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

    <data>
        <variable
            name="userInfo"
            type="com.demo.demodatabinding.UserInfo" />
    </data>

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.demo.demodatabinding.MainActivity">

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{userInfo.name}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.358"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.107"
            tools:text="name" />

        <TextView
            android:id="@+id/et_age"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="64dp"
            android:text='@{userInfo.age + ""}'
            android:hint="age"
            app:layout_constraintEnd_toStartOf="@+id/tv_name"
            app:layout_constraintTop_toBottomOf="@+id/tv_name"
            tools:text="age" />

        <TextView
            android:id="@+id/tv_is_student"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="144dp"
            android:text='@{userInfo.isStudent?"student":"非student"}'
            app:layout_constraintEnd_toStartOf="@+id/tv_name"
            app:layout_constraintTop_toBottomOf="@+id/tv_name"
            tools:text="is_student" />

    </android.support.constraint.ConstraintLayout>
</layout>

指定变量的名字是userInfo,变量的类型是com.demo.demodatabinding.UserInfo。这里的类型也可以不写全包名,但是必须先导包,代码如下:

<data>
    <import type="com.demo.demodatabinding.UserInfo"/>
    <variable
        name="userInfo"
        type="UserInfo" />
</data>

4、代码处理

在MainActivity中定义代码如下:

ActivityMainBinding mainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
userInfo = new UserInfo("王羲之", 18, false);
mainBinding.setUserInfo(userInfo);

以前我们是在onCreate方法中通过setContentView去设置布局,但现在不一样了,现在我们是通过DataBindingUtil类的一个静态方法setContentView设置布局,同时该方法会返回一个对象,什么对象?这个对象有点特殊,它是一个自动生成的类的对象,这个类就是ActivityMainBinding 。这个生成类的类名规则如下:将我们布局文件的首字母大写,并且去掉下划线,将下划线后面的字母大写,加上Binding组成。
运行界面如下图:
在这里插入图片描述
我们没有findViewById和setText,但是界面上还是显示了,这就是DataBinding的厉害。

5、单向绑定数据

上面的代码还不能让我们满意,因为我们更改对象userInfo时,界面上的数据并没有更新。
1)、使用BaseObservable
让UserInfo继承BaseObservable,在getAge()方法上添加注解@Bindable,setAge()中添加notifyPropertyChanged(BR.age);(age就是我们要绑定的属性名)代码如下:

public class UserInfo extends BaseObservable{
    private String name;
    private int age;
    private boolean isStudent;

    public String getName() {
        return name;
    }

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

    @Bindable
    public int getAge() {
        return age;
    }

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

    public boolean isStudent() {
        return isStudent;
    }

    public void setStudent(boolean student) {
        isStudent = student;
    }

    public UserInfo(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public UserInfo(String name, int age, boolean isStudent) {
        this.name = name;
        this.age = age;
        this.isStudent = isStudent;
    }
}

然后每次调用userInfo.setAge(age++);界面上的age就会改变。
2)、使用ObservableField定义属性名
上面的方法可以解决我们之前的问题,但是还是需要写很多代码,使用ObservableField可以减少很多代码。
UserInfo的代码如下:

public class UserInfo {
    public ObservableField<String> name = new ObservableField<>();
    public ObservableField<Integer> age = new ObservableField<>();
    public ObservableField<Boolean> isStudent = new ObservableField<>();
}

上面代码是不是比以前的简单多了。
设置age新值方式也有所不同,代码如:userInfo.age.set(age++);

6、双向数据绑定

上面介绍可以实现变量值改变后界面也跟着改变,但是界面的值改变变量却没有改变。实现双向数据绑定对我们要更改的代码很少。只需要添加一个=即可,代码如:将以前的’@{userInfo.isStudent?“student”:“非student”}‘改为’@{=userInfo.isStudent?“student”:“非student”}'即可。我们将age对应的控件改为EditText,每次EditText数据改变后我们获取age的值都改变了。

三、事件绑定

大家都知道,在xml中我们可以给button设置一个onClick来达到事件的绑定,现在DataBinding也提供了事件绑定,而且不仅仅是button。

1、在MainActivity中定义点击处理

1)、MainActivity定义onClick函数,代码如下:

public void onClick(View view){
    Toast.makeText(this, view.getId() + ">>onClick", Toast.LENGTH_SHORT).show();
}

2)、布局文件中定义
在data节点下添加如下代码:

<variable
    name="mainActivity"
    type="com.demo.demodatabinding.MainActivity" />

点击按钮设置如下:

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="60dp"
    android:layout_marginTop="84dp"
    android:onClick="@{mainActivity.onClick}"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/tv_is_student" />

3)、在MainActivity中调用如下代码:

mainBinding.setMainActivity(this);

2、单独写一个类定义点击处理函数

1)、新建EventHandler类,代码如下:

public class EventHandler {
    public void handleClick(View view){
        Toast.makeText(view.getContext(), view.getId() + ">>onClick", Toast.LENGTH_SHORT).show();
    }
}

2)、布局文件中定义
在data节点下添加如下代码:

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="60dp"
    android:layout_marginTop="84dp"
    android:onClick="@{eventHandler.handleClick}"
    android:text="@{mainActivity.str}"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/tv_is_student" />

3)、在MainActivity中调用如下代码:

mainBinding.setEventHandler(new EventHandler());

四、xml中的表达式

xml文件中支持的运算符如下:

数学运算符 + - / * %
字符串拼接 +
逻辑运算 && ||
二进制运算 & | ^
一元运算符 + - ! ~
位运算符 >> >>> <<
比较运算符 == > < >= <=
instanceof
Grouping ()
文字 - character, String, numeric, null
类型转换 cast
方法调用 methods call
字段使用 field access
数组使用 [] Arrary access
三元运算符 ? :

不支持的运算符如下:

this
super
new
Explicit generic invocation

五、设置别名

1、为import的类设置别名

假如我们import了两个相同名称的类咋办?别怕,别名来拯救你!如下:

<data>
  <import type="xxx.Name" alias="MyName">
  <import type="xxx.xx.Name">
</data>

<TextView xxx:@{MyName.getName()}>
<TextView xxx:@{Name.getName()}>

2、自定义Binding类的名称

代码如下:

<data class=".Custom">
...
</data>

DataBindingUtils.setContentView返回的binding类名就是:你的应用包名.Custom。
源码请点击

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值