文章目录
基础示例
1.在module的build.gradle
的android
节点中添加如下配置:
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_width
或android: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" />
<!--泛型的支持会在编译时期报红线,但是是可以直接运行的
但是需要通过转义字符才行,如:<号用<表示;>号用>表示;-->
<variable
name="list"
type="List<String>" />
<variable
name="map"
type="Map<String,Object>" />
<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<String>
和Map<String,Object>
原因是在data
中,有些字符是必须用转义字符才能编译通过。
最常用的转义字符列表
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
,这里有ObservableField
,ObservableBoolean
,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
除了支持ObservableField
,ObservableBoolean
,ObservableInt
等基础变量类型以外,当然也支持集合框架,比如:ObservableArrayMap
,ObservableArrayList
。使用和普通的Map
、List
基本相同。
activity_main.xml:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="list"
type="android.databinding.ObservableArrayList<String>"/>
<variable
name="map"
type="android.databinding.ObservableArrayMap<String,Object>"/>
<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