1. DataBinding
通过声明的方式,将 xml 布局中的组件与程序中的源数据进行绑定的框架库。当数据变化的同时组件能够及时同步并更新,减少Activity 中 View 的定义以及初始化,代码更加简洁。
2. DataBinding 的使用
2.1 在项目中对应 module 的 build.gradle 文件中添加 dataBinding 可用的配置:
android {
...
...
dataBinding {
enabled = true
}
}
2.2 添加绑定组件需要的实体类:
package cn.zzw.jetpackdemo.bean;
public class UserInfo {
private String name;
private int 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;
}
@Override
public String toString() {
return "My name is "+name+", I am "+age+" years old.";
}
}
2.3 xml 中将实体类与组件进行绑定
<?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="handles"
type="cn.zzw.jetpackdemo.MainActivity" />
<variable
name="userInfo"
type="cn.zzw.jetpackdemo.bean.UserInfo" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{userInfo.toString()}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/mBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取信息"
android:onClick="@{handles.click}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.120000005" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
在 xml 中,以 <layout> </layout> 为根布局,固定格式如下:
<layout 所有的命名空间的内容>
<data>
</data>
<根布局>
...
</根布局>
</layout>
在 data 标签下,通过 variable 标签可以指定类,然后在控件的属性值中就可以使用,具体使用方法如上所示。
2.4 Activity 中具体代码
package cn.zzw.jetpackdemo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import java.util.Random;
import cn.zzw.jetpackdemo.bean.UserInfo;
import cn.zzw.jetpackdemo.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
ActivityMainBinding mainBinding;
UserInfo userInfo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
mainBinding.setHandles(this);
userInfo = new UserInfo();
userInfo.setName("zuowei.zhang");
}
public void click(View v) {
Log.e("zzw", "click");
switch (v.getId()) {
case R.id.mBtn:
Log.e("zzw", "mBtn click");
Random ra = new Random();
int age = ra.nextInt(120);
userInfo.setAge(age);
mainBinding.setUserInfo(userInfo);
break;
}
}
}
Android studio会根据 layout 文件自动生成一个默认的 Binding 类,类名是根据layout文件名生成的,并有"Binding"后缀结束。例如:activity_main.xml 生成的 Binding 类为 ActivityMainBinding,具体使用方式如上所示。
2.5 结果
3. 数据的更新
在上面的例子中,虽然做到了实时的更新数据,但是只是一种伪更新数据,因为是不断的调用 mainBinding.setUserInfo,重新进行了赋值。
3.1 BaseObservable
将 User 类继承 BaseObservable,并在 set 方法中调用 notifyChange() 方法。
package cn.zzw.jetpackdemo.bean;
import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
import cn.zzw.jetpackdemo.BR;
public class UserInfo extends BaseObservable {
private String name;
private int 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;
notifyChange();
}
@Override
public String toString() {
return "My name is " + name + ", I am " + age + " years old.";
}
}
在使用的时候,只需要调用,setAge 就可以做到数据的更新。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
mainBinding.setHandles(this);
userInfo = new UserInfo();
userInfo.setName("zuowei.zhang");
userInfo.setAge(120);
mainBinding.setUserInfo(userInfo);
}
public void click(View v) {
Log.e("zzw", "click");
switch (v.getId()) {
case R.id.mBtn:
Log.e("zzw", "mBtn click");
Random ra = new Random();
int age = ra.nextInt(120);
userInfo.setAge(age);
break;
}
}
3.2 ObservableField
package cn.zzw.jetpackdemo.bean;
import androidx.databinding.ObservableField;
import androidx.databinding.ObservableInt;
public class UserInfo {
public final ObservableField<String> name = new ObservableField<>();
public final ObservableInt age =new ObservableInt();
}
通过 ObservableField,上面的 UserInfo 变成了两行,大大的简化了代码,调用的代码与上面一样。ObservableField<T>,T为泛型,还可以使用 ObservableBoolean, ObservableByte, ObservableChar, ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble, ObservableParcelable等具体的类型。