Android-0.DataBinding基础示例

点击下载源码

基础示例

1.在module的build.gradleandroid节点中添加如下配置:

android {
    // 启用dataBinding
    dataBinding{
        enabled = true;
    }
    ......
 }

2.创建一个简单的UserBean类:

public class UserBean {
    private String name; //姓名
    private int age; //年龄

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

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

注意get/set方式是需要定义的,不然会提示:

msg:Could not find accessor xxx

3.使用了DataBinding之后的Activity的布局文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="user"
            type="myvideo.duowan.com.databindingdemo.bean.UserBean"/>
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}"/>

        <!--注意:这里age是int类型,必须转化为String,否则会运行时异常-->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(user.age)}"/>
    </LinearLayout>
</layout>

根节点变成了layout,里面包括了data节点和传统的布局。
data节点中声明一个variable变量,名字叫user,关联了type为UserBean对象。
而TextView中使用了android:text="@{user.name}"android:text="@{String.valueOf(user.age)}"来直接访问UserBean的两个私有成员.

根结节变成layout后,不要有android:layout_widthandroid:layout_height,不然会报错:error:
duplicate attribute.

4.MainActivity

import myvideo.duowan.com.databindingdemo.databinding.ActivityMainBinding;// 导入

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 根据布局文件的名称生成Binding类的规则为:以大写形式开始,删除下划线(_),并使用驼峰命名,然后后缀为“Binding”
        // eg: activity_main-->ActivityMainBinding
        // 同时必须import 包名.databinding.ActivityMainBinding;
        ActivityMainBinding  binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        UserBean userBean = new UserBean("张三",25);
        binding.setUser(userBean);
    }
}

根据布局文件的名称生成Binding类的规则为:以大写形式开始,删除下划线(_),并使用驼峰命名,然后后缀为“Binding”。例如:activity_main–>ActivityMainBinding

ActivityMainBinding是系统自动生成的类,需要import 包名.databinding.ActivityMainBinding;

binding.setUser是自动生成的函数,set/get + variable变量的名字user(第一个字母大写)

运行结果:

系统自动生成的ActivityMainBinding不能被调试,一般位于databinding\ActivityMainBinding.java

1.在xml中引入一些基础变量Variables

activity_main.xml:

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

    <data>

        <variable
            name="str"
            type="String" />

        <variable
            name="age"
            type="int" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{str}" />

        <!--注意:这里age是int类型,必须转化为String,否则会运行时异常-->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(age)}" />
    </LinearLayout>
</layout>

MainActivity:


import myvideo.duowan.com.databindingdemo.databinding.ActivityMainBinding;// 导入

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 根据布局文件的名称生成Binding类的规则为:以大写形式开始,删除下划线(_),并使用驼峰命名,然后后缀为“Binding”
        // eg: activity_main-->ActivityMainBinding
        // 同时必须import 包名.databinding.ActivityMainBinding;
        ActivityMainBinding  binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        binding.setStr("张三");
        binding.setAge(25);
    }
}

运行结果和前面一样,注意这时使用的是binding.setStr+binding.setAge,分别对应variable变量的名字name="str"+ name="age"

2.引入一些高级变量Variables

在上面,我们学会了如何在xml中定义变量,以及在控件中使用。同样,我们可以在data中定义像List、Map,数组等这样的集合变量,只是它的实现稍微有点不同,下面就一起来看看是如何定义以及使用的。
activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <import type="java.util.List" />
        <import type="java.util.Map" />
        <!--泛型的支持会在编译时期报红线,但是是可以直接运行的
       但是需要通过转义字符才行,如:<号用&lt表示;>号用&gt表示;-->
        <variable
            name="list"
            type="List&lt;String&gt;" />
        <variable
            name="map"
            type="Map&lt;String,Object&gt;" />
        <variable
            name="array"
            type="String[]" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{list[0]}" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{list.get(1)}" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{map[`key0`]}" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{map.get(`key1`)}" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{array[0]}" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{array[1]}" />
    </LinearLayout>
</layout>

大家可以看到,list和map这里我没有用List<String>Map<String,Object>,而是用的List&lt;String&gt;Map&lt;String,Object&gt;原因是在data中,有些字符是必须用转义字符才能编译通过。

最常用的转义字符列表

注意: android:text=""这里,我用的是双引号的写法,官方还有一种单引号的写法。
android:text='@{map["key0"]}'

双引号当然也是可以的,只是你的key要用``包裹,注意,这个不是单引号,而是Tab键上面的那个键的那个点。

MainActivity:

import myvideo.duowan.com.databindingdemo.databinding.ActivityMainBinding;// 导入

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        List<String> list = new ArrayList<>();
        list.add("list1");
        list.add("list2");
        binding.setList(list);

        HashMap<String, Object> map = new HashMap<>();
        map.put("key0", "map_value0");
        map.put("key1", "map_value1");
        binding.setMap(map);

        String[] arrays = {"字符串1", "字符串2"};
        binding.setArray(arrays);
    }
}

注意 android:text="@{map[key0]}" 对应代码中map.put("key0", "map_value0");,运行结果如下:

3.xml中引用表达式

举几个例子,还有很多,大多数Java表达式都是支持的

android:text="@{String.valueOf(age)}"
android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"
android:text='@{"iname:" +user.name}'

此外还支持null合并操作,它的符号是??,意思是:如果左边的对象非空则选择左边,否则选择右边。

android:text="@{user.displayName ?? user.lastName}"
//等价于
android:text="@{user.displayName != null ? user.displayName : user.lastName}"

支持的表达式语言:

  • 数学计算 + - / * %
  • 字符串连接 +
  • 逻辑 && ||
  • 二进制 & | ^
  • 一元 + - ! ~
  • 位移 >> >>> <<
  • 比较 == > < >= <=
  • instanceof
  • 组 ()
  • 字面量 - 字符,字符串,数字, null
  • 类型转换
  • 函数调用
  • 字段存取
  • 数组存取 []
  • 三元运算符 ?:

不支持的操作符:

  • this
  • super
  • new
  • 显式泛型调用

4.设置别名alias

如果我们import了两个不同路径,但名称相同的类,可以借助于别名来解决,别名借助alias字段来标识,例如:

activity_main.xml:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <import type="myvideo.duowan.com.databindingdemo.bean.UserBean"/>
        <!--不同路径下有2个相同名字的类,那么给其中一个起一个别名,用alias表示-->
        <import type="myvideo.duowan.com.databindingdemo.bean.user.UserBean" alias="UserBean2"/>

        <variable
            name="user"
            type="UserBean"/>
        <variable
            name="user2"
            type="UserBean2"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{"姓名:"+user.name}'/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{"user2:"+user2.content}'/>

    </LinearLayout>
</layout>

MainActivity:

import myvideo.duowan.com.databindingdemo.databinding.ActivityMainBinding;// 导入

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);


        UserBean userBean = new UserBean("张三",24);
        binding.setUser(userBean);

        myvideo.duowan.com.databindingdemo.bean.user.UserBean userBean2 = new myvideo.duowan.com.databindingdemo.bean.user.UserBean("我是user2");
        binding.setUser2(userBean2);
    }
}

运行结果如下:

5.include中的使用

在使用命名空间的布局中,变量可以传递到任何 include 布局中。

<?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">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <include layout="@layout/name"
          app:user="@{user}"/>
       <include layout="@layout/contact"
          app:user="@{user}"/>
   </LinearLayout>
</layout>

注意:在include的layout文件中必须要有user variable。

6.事件处理

大家都知道,我们经常需要处理View的点击事件,在xml中android:onClick 可以指定 Activity 中的函数,Data Binding 也允许处理从视图中发送的事件。

下面给出几种实现方式:

  • 布局中引入OnClickListener的变量
  • 方法调用
布局中引入OnClickListener的变量

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="clickListener"
            type="android.view.View.OnClickListener"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:id="@+id/click_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{clickListener}"
            android:text="点我"/>

        <Button
            android:id="@+id/click2_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{clickListener}"
            android:text="点我2"/>
    </LinearLayout>
</layout>

MainActivity:

import myvideo.duowan.com.databindingdemo.databinding.ActivityMainBinding;// 导入

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        binding.setClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.click_btn) {
            Toast.makeText(this, "点击了1", Toast.LENGTH_SHORT).show();
        } else if (v.getId() == R.id.click2_btn) {
            Toast.makeText(this, "点击了2", Toast.LENGTH_SHORT).show();
        }
    }
}

注意 binding.setClickListener(this);对应name="clickListener"。,运行结果如下:

方法调用

相比较于在android:onClick中指定Activity的一个方法,它的优势在于表达式会在编译时处理,如果方法不存在或者方法签名不对,编译将会报错。
新建一个class:

public class HandlerClass {
    public void onClickFriend(View view){
        Toast.makeText(view.getContext(), "onClickFriend", Toast.LENGTH_SHORT).show();
    }
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="handler1"
            type="myvideo.duowan.com.databindingdemo.handler.HandlerClass"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="点击"
            android:onClick="@{handler1::onClickFriend}"/>
        <!-- 注意:函数名和监听器对象必须对应 -->
        <!-- 函数调用也可以使用 `.` , 如handler1.onClickFriend , 不过已弃用 -->
    </LinearLayout>
</layout>

MainActivity:

import myvideo.duowan.com.databindingdemo.databinding.ActivityMainBinding;// 导入
import myvideo.duowan.com.databindingdemo.handler.HandlerClass;

public class MainActivity extends AppCompatActivity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        binding.setHandler1(new HandlerClass());
    }

注意观察:关联到HandlerClass的是name="handler1",通过android:onClick="@{handler1::onClickFriend}关联到了HandlerClass的函数onClickFriend,最后通过binding.setHandler1(new HandlerClass());设置

双向绑定

我们学会了通过binding为我们的变量设置数据,但是不知道你有没有发现一个问题,当我们数据改变的时候会怎样?数据是跟随着改变呢?还是原来的数据呢?这里告诉你答案:很不幸,显示的还是原来的数据?那有没有办法让数据源发生变化后显示的数据也随之发生变化?先来想想ListView是怎么做的, ListView的数据是通过Adapter提供的,当数据发生改变时,我们通过notifyDatasetChanged通过UI去改变数据,这是通过一个观察者模式来实现的,很幸运,查阅源码后发现DataBinding也是通过观察者模式来实现的。

1.BaseObservable

我们可以通过Observable的方式去通知UI刷新数据,Observable 是一个包含添加/移除 listener 的机制的接口,为了简化开发,Android 原生提供了一个基类 BaseObservable 来实现 listener 注册机制。这个类也实现了字段变动的通知,只需要在 getter 上使用 Bindable 注解,并在 setter 中通知更新即可。

定义一个实体类,并继承BaseObservable:

import myvideo.duowan.com.databindingdemo.BR;// Package + .BR
public class DoubleBindBean extends BaseObservable {
    //BR 是编译阶段生成的一个类,功能与 R.java 类似,用 @Bindable 标记过 getter 方法会在 BR 中生成一个 entry,当我们
    //通过代码可以看出,当数据发生变化时还是需要手动发出通知。 通过调用notifyPropertyChanged(BR.firstName)来通知系统 BR.firstName 这个 entry 的数据已经发生变化,需要更新 UI。
    private String content;
    public DoubleBindBean(String content) {
        this.content = content;
    }

    @Bindable
    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
        notifyPropertyChanged(BR.content);//通知系统数据源发生变化,刷新UI界面
    }
}

其中notifyPropertyChanged(BR.content);就是观察者模式的广播通知。其中BR是编译阶段生成的一个类,功能与 R.java 类似,用 @Bindable 标记过 getxxx() 方法会在 BR 中生成一个 entry,如下所示:

所以需要手工import myvideo.duowan.com.databindingdemo.BR;// Package + .BR, 当数据发生变化时需要调用 notifyPropertyChanged(BR.content) 通知系统 BR.content这个 entry 的数据已经发生变化以更新UI。

activity_main.xml:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="doubleBindBean"
            type="myvideo.duowan.com.databindingdemo.bean.DoubleBindBean"/>
        <variable
            name="onClickListener"
            type="android.view.View.OnClickListener"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{doubleBindBean.content}"/>
        <Button
            android:id="@+id/change_content_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{onClickListener}"
            android:text="BaseObservable方式改变内容"/>
    </LinearLayout>
</layout>

MainActivity:

import myvideo.duowan.com.databindingdemo.databinding.ActivityMainBinding;// 导入
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private boolean flag;
    private DoubleBindBean doubleBindBean;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        doubleBindBean = new DoubleBindBean("我是原始内容");
        binding.setDoubleBindBean(doubleBindBean);
        binding.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.change_content_btn:
                flag = !flag;
                doubleBindBean.setContent(flag ? "我是更新后的内容" : "我是原始内容");
                break;
            default:
                break;
        }
    }
}

其实就是doubleBindBean.setContent调用了广播通知,让绑定者接收到消息。运行效果:

2.ObservableFields家族

上面使用BaseObservable已经非常容易了,但是google工程师还不满足,继续给我们封装了一系列的ObservableFields,这里有ObservableFieldObservableBoolean,ObservableByte,ObservableChar,ObservableShort,ObservableInt,ObservableLong,ObservableFloat,ObservableDouble,ObservableParcelable 它的实现就更简洁了,如下:

public class DoubleBindBean2 {
    //变量需要为public
    public final ObservableField<String> username = new ObservableField<>();
//    public String getUsername(){
//        return this.username.get();
//    }

这里要特别注意,DoubleBindBean2不要写getUsername,可能是覆盖吧,不然无效。

activity_main.xml:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="doubleBindBean2"
            type="myvideo.duowan.com.databindingdemo.bean.DoubleBindBean2"/>
        <variable
            name="onClickListener"
            type="android.view.View.OnClickListener"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{doubleBindBean2.username}"/>
        <Button
            android:id="@+id/change_content_btn2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{onClickListener}"
            android:text="ObservableFields方式改变内容"/>
    </LinearLayout>
</layout>

MainActivity:

import myvideo.duowan.com.databindingdemo.databinding.ActivityMainBinding;// 导入
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private boolean flag2;
    private DoubleBindBean2 doubleBindBean2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        doubleBindBean2 = new DoubleBindBean2();
        doubleBindBean2.username.set("我是原始内容2");
        binding.setDoubleBindBean2(doubleBindBean2);
        binding.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.change_content_btn2:
                flag2 = !flag2;
                doubleBindBean2.username.set(flag2 ? "我是更新后的内容2" : "我是原始内容2");
                break;
            default:
                break;
        }
    }
}

注意doubleBindBean2.username.set("我是原始内容2");直接使用了成员变量,你可以自己封装一个简单函数调用。运行效果:

3.Observable Collections

除了支持ObservableFieldObservableBooleanObservableInt等基础变量类型以外,当然也支持集合框架,比如:ObservableArrayMapObservableArrayList。使用和普通的MapList基本相同。

activity_main.xml:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="list"
            type="android.databinding.ObservableArrayList&lt;String&gt;"/>
        <variable
            name="map"
            type="android.databinding.ObservableArrayMap&lt;String,Object&gt;"/>
        <variable
            name="onClickListener"
            type="android.view.View.OnClickListener"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{list[0]}"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{map["key0"]}'/>

        <Button
            android:id="@+id/change_content_btn3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{onClickListener}"
            android:text="list改变内容"/>
        <Button
            android:id="@+id/change_content_btn4"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{onClickListener}"
            android:text="map改变内容"/>
    </LinearLayout>
</layout>

MainActivity:

import myvideo.duowan.com.databindingdemo.databinding.ActivityMainBinding;// 导入
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ObservableArrayList<String> list = new ObservableArrayList<>();
    private ObservableArrayMap<String, Object> map = new ObservableArrayMap<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        list.add("list0");
        list.add("list1");
        binding.setList(list);
        map.put("key0", "key0_value0");
        map.put("key1", "key0_value1");
        binding.setMap(map);

        binding.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.change_content_btn3:
                list.set(0, "after change list");
                break;
            case R.id.change_content_btn4:
                map.put("key0", "after change key0_value0");
                break;
            default:
                break;
        }
    }
}

运行结果:

4.Fragment实现双向绑定

不知道大家注意没有,上面的代码我们都是在activity中通过DataBindingUtil.setContentView来加载的布局的,现在有个问题了,如果我们是在Fragment中使用呢?Fragment没有setContentView怎么办?不要着急,Data Binding也提供了inflate的支持!
学生类:

package myvideo.duowan.com.appfragment;
import android.databinding.BaseObservable;
import android.databinding.Bindable;
public class Student extends BaseObservable {
    private String name;
    private int age;

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

    @Bindable
    public String getName() {
        return name;
    }

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

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

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

布局文件:
activity_main.xml:

<RelativeLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </FrameLayout>

</RelativeLayout>

frag_layout.xml:

<layout
    xmlns:android="http://schemas.android.com/apk/res/android">
    <data class=".Custom">
        <import type="myvideo.duowan.com.appfragment.Student"/>
        <variable
            name="stu"
            type="Student"/>
        <variable
            name="frag"
            type="myvideo.duowan.com.appfragment.MyFragment"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{frag.click}"
            android:text="@{stu.name}" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(stu.age)}"/>
    </LinearLayout>
</layout>

MyFragment.java:

public class MyFragment extends Fragment {
    private Student mStu;
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        myvideo.duowan.com.appfragment.Custom binding = DataBindingUtil.inflate(inflater, R.layout.frag_layout,container,false);
        mStu = new Student("loader", 20);
        binding.setStu(mStu);
        binding.setFrag(this);
        return binding.getRoot();
    }

    public void click(View view){
        mStu.setName("qibin");
        mStu.setAge(18);
    }
}

注意myvideo.duowan.com.appfragment.Custom,对应上面的 <data class=".Custom">,这和activity_main.xml对应ActivityMainBinding有点差异。
这里我们使用了DataBindingUtil.inflate方法,接受4个参数,第一个参数是一个LayoutInflater对象,正好,我们这里可以使用onCreateView的第一个参数,第二个参数是我们的布局文件,第三个参数是一个ViewGroup,第四个参数是一个boolean类型的,和在LayoutInflater.inflate一样,后两个参数决定了是否向container中添加我们加载进来的布局。
最后ViewDataBinding有一个方法getRoot可以返回一个View对象。
运行结果如下:

参考:
https://www.jianshu.com/p/53925ccb900e
https://blog.csdn.net/qibin0506/article/details/47393725

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值