数据绑定库(DataBinding)是一种支持库,借助该库,您可以使用声明性格式将布局中的界面组件绑定到应用中的数据源。 –谷歌
意思就是,一些UI组件和应用的一些数据绑定在一起,数据改变<—>UI改变. 无需写代码,达到两者自动同步的效果.DataBinding通常用户MVVM模式在Android的实现.连接View和ViewModel.
使用方法
配置
在app的gradel中加入代码
1 | android{ |
创建数据
1 | public class User{ |
这里定义了了一个User类,里面有一天数据name.
改变布局
打开xml布局文件, 把光标放在父布局(根布局),然后 Alt+Enter,选择“Convert to data binding layout” 布局自动转换成DataBinding布局。像这样:
1 |
|
可以看到布局父布局是 layout,它有两个子布局 data 和 一个普通的view布局。
data布局用于声明数据表变量及其类型。有两种方法
1 | <data> |
第二种,import导入类型,该类型可以被多次使用
1 | <import type="com.example.databindtest.User"/> |
第二种还可以用alias重命名该类型
1 | <import type="com.example.databindtest.User" |
至于原始布局和从前一样,这里我定义了一个EditText
绑定UI和数据
这里绑定将EditText和User的name绑定在一起,EditText加入 android:text”@{}” 就行
1 | <EditText |
Activity代码
1 |
|
单向绑定
方式一:BaseObservable
数据表继承BaseObservable 用注释 @Bindable 绑定数据。
BaseObservable提供了两个刷新数据的方法
- notifyChange(); //刷新所有值
- notifyPropertyChanged(BR.name); 刷新BR指定值
实例代码如下:
1 | public class User extends BaseObservable { |
到这里便实现了单向绑定即,数据改变 -> UI改变。
方式二:ObservableField
用BaseObservable绑定要注解,还要notifyPropertyChanged,当数据比较多的时候要写蛮多代码的。所以官方还提供一系列 ObservableField。其中包括ObservableBoolean, ObservableByte, ObservableChar, ObservableShort, ObservableInt, ObservableLong, ObservableFloat ObservableDouble, 以及 ObservableParcelable等。用法:
- 数据表这样写:
1 | public class User{ |
- Activity这样写
1
2
3user = new User();
binding.setUser(user);
user.name.set("初始");双向绑定
想要达到数据改变 ->UI改变,UI改变 -> 数据改变。改变布局的一行代码就行了
android:text=”@{}” 改成 android:text=”@={}”
1 | <EditText |
点击事件
定义点击事件响应类,先在activity写逻辑
1
2
3
4
5
6
7
8
9
10public void onClick(View view) {
switch (view.getId()){
case R.id.tv1:
Log.d("测试","按钮1");
break;
case R.id.tv2:
Log.d("测试","按钮2");
break;
}
}data中添加声明
1 | <data> |
- button引用
1 | <Button |
- 最后在activity绑定一下就行了
1 | binding.setMainActivity(this); |
图片的显示
- User数据表添加一条数据 imaUrl
1 | public class User extends BaseObservable { |
- 写逻辑
需要导入Glide库这里通过 @BindingAdapter 注解拿到url1
2
3
4
5
public static void loadIma(ImageView imageView, String url){
Log.d("测试","图片测试+utl:"+url);
Glide.with(imageView.getContext()).load(url).into(imageView);
} - 布局
1 | <ImageView |
看到这里有一个属性 app:imaUrl=”” 便是上面注解 @BindingAdapter 里面的
- 最后在activity绑定一下就行了。如果加载的是网络图片记得给权限
1 | binding.setUser(user); |
- 更新图片
如果数据表数据变了,图片并不会同步改变。想要更新ImageView需要重新绑定一下。
1 | user.setImaUrl("newImaUrl"); |
使用RecyclerView
- 数据表
1 | public class User{ |
写个item布局,一个文字加一张图片,数据用上面那个表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<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.databindtest.User" />
</data>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="40dp"
android:text="@={user.name}"/>
<ImageView
android:layout_width="0dp"
android:layout_weight="9"
android:layout_height="100dp"
app:imaUrl="@{user.imaUrl}"/>
</LinearLayout>
</layout>适配器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36public class MyAdapter extends RecyclerView.Adapter {
private Context context;
List<User> userList;
public MyAdapter(Context context, List<User> userList) {
this.context = context;
this.userList = userList;
}
public RecyclerView.ViewHolder onCreateViewHolder(int viewType) ViewGroup parent, {
LayoutInflater inflater = LayoutInflater.from(context);
ItemBinding binding = DataBindingUtil.inflate(inflater,R.layout.item,parent,false);
return new myHolder(binding.getRoot());
}
public void onBindViewHolder(int position) RecyclerView.ViewHolder holder, {
ItemBinding binding = DataBindingUtil.getBinding(holder.itemView);
binding.setUser(userList.get(position));
binding.executePendingBindings();
}
public int getItemCount() {
if(userList == null){
return 0;
}else return userList.size();
}
public class myHolder extends RecyclerView.ViewHolder{
public myHolder( View itemView){
super(itemView);
}
}
}可以看到适配器和传统的用法是差不多的,主要看 onCreateViewHolder() 和onBindViewHolder() 这两个函数。
其他部分适合以前一样使用即可。