DataBinding的简单使用
Table of Contents
参考文章:https://www.jianshu.com/p/ba4982be30f8
环境配置
在 gradle 里添加对 dataBinding 的支持:
android{
...
dataBinding{
enable = true
}
}
安装插件:Databinding Support 对 layout 文件支持,Data Binding Formatter 对 class 文件支持
使用
编写布局文件,使用变量:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="viewModel"
type="com.example.Article"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/activity_horizontal_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.title}"
android:textSize="@dimen/base_font_size_large_18"
android:textStyle="bold"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.view+`次浏览`}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.like+`个喜欢`}"
android:layout_marginLeft="10dp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:value="@={viewModel.reader}"/>
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
bind:bindSrcToImage="@{viewModel.image}"
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="已阅"
android:onClick="@{viewModel::onClickRead}"/>
</LinearLayout>
</layout>
在 layout 文件中使用 Article 对象,要想把 Article 对象的相关字段绑定在 UI 上,还需要申明这些字段是“可观察的”,可以这样实现:
- 继承 BaseObservable,然后用@Bindable 注解需要观察的属性
- 使用 ObseravbleField 类型包裹属性
Android studio 会根据 layout 文件自动生成一个默认的 Binding 类,类名是根据 layout 文件名生成的,并有"Binding"后缀结束。例如:activity_article.xml 生成的 Binding 类为 ActivityArticleBinding,可用如下方式使用 Binding 类:
ActivityArticleBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_article);
Article article = new Article();
binding.setViewModel(article);
或者:
ActivityArticleBinding binding = ActivityArticleBinding.inflate(getLayoutInflater());
在 RecyclerView 的 adapter 中的 item 里使用 DataBinding:
ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
//or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
在 layout 中绑定的 onClickRead 方法只需要在 Article 中实现一个 public 的 onClickRead 方法即可
在 layout 中申明的 bindSrcToImage 属性需要加@BindingAdapter 注解实现逻辑,如:
@BindingAdapter("bind:bindSrcToImage")
public static void setSrcToImage(ImageView imageView,String src){
Glide.with(mContext).load(src).into(imageView);
}
使用同样方法可以覆盖控件的原 set 方法实现,且可以同时处理多个属性,如:
@BindingAdapter({"android:onClick", "android:clickable"})
public static void setOnClick(View view, View.OnClickListener clickListener,
boolean clickable) {
view.setOnClickListener(clickListener);
view.setClickable(clickable);
}
使用 import 标签导入类,然后可以使用类的静态资源:
<data>
<import type="android.view.View"/>
</data>
<TextView
android:text="@{article.content}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{article.isFold ? View.VISIBLE : View.GONE}"/>
有时候我们可能不知道 Binding 类的名称,比如 RecyclerView.Adapter 中 item 布局可能有很多,并不会对应特定的 Binding 类,但是仍然需要通过 onBindViewHolder(VH, int)去绑定数据,下面的例子是,所有的子布局都有一个"item"变量(所有申明的变量都在 BR 文件里面),通过 ViewDataBinding 基类去完成绑定:
public void onBindViewHolder(BindingHolder holder, int position) {
final T item = mItems.get(position);
holder.getBinding().setVariable(BR.item, item);
holder.getBinding().executePendingBindings();
}
有时候我们需要自定义属性变化的业务逻辑,我们可以给 Observable 变量设置变化监听:
ObservableInt flag = new ObservableInt();
flag.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
@Override
public void onPropertyChanged(Observable sender, int propertyId) {
if(sender.get() == 0){
finish();
}
}
});
有时候我们想要在类里面申明的数据类型和 layout 里面使用的数据类型不一样,那我们可以使用@BindingConversion 注解实现,比如将整型颜色值转化为 Drawable:
@BindingConversion
public static ColorDrawable convertColorToDrawable(int color) {
return new ColorDrawable(color);
}