DataBinding介绍
DataBinding类似于ButterKnife,可以将数据结构与XML绑定,节省了很多Activity中UI的代码,比如说findViewById
等。也可以提升APP性能,帮助避免内存泄露以及空指针的问题。
DataBinding的使用
- 在
app
模块的build.gradle
中添加DataBinding配置:
android {
...
dataBinding {
enabled = true
}
}
- 定义XML对应的数据结构
package com.example.aactest;
public class Data {
private String name;
private String title;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
- 创建layout.xml文件(如activity_main.xml):
与原来的XML文件不同的是,根节点的为
layout
,而不是具体的ViewGroup。并且将与该xml绑定的数据需要在data
标签中定义,并且在下方的View中将属性与子View绑定。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.example.aactest.Data" />
<variable
name="aacdata"
type="com.example.aactest.Data" />
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{aacdata.title}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{aacdata.name}" />
</android.support.constraint.ConstraintLayout>
</layout>
- 编译完成后,在
/app/build/generated/source/apt/debug
下会新增一个packagename.databinding
的文件夹,并且根据layout.xml编译生成的文件,而该文件名就是xml对应的名称。
比如:包名为com.example.aactest的应用,在上述目录下会生成com.example.aactest.databinding的文件夹,而activity_main.xml就会生成ActivityMainBinding.java文件
- 使用DataBinding绑定具体数据
在生成的ActivityMainBinding文件中,就会有数据部分的
set
,get
方法,在调用完set
方法更新完Binding中的数据后,对应的View也会更新。
public class MainActivity extends AppCompatActivity {
ActivityMainBinding mBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
final Data data=new Data();
data.setTitle("This is Title");
data.setName("This is User Name");
mBinding.setTd(data);
Handler handler = new Handler(new Handler.Callback() {
@Override public boolean handleMessage(Message message) {
data.setTitle("Change Title");
mBinding.setTd(data);
return false;
}
});
handler.sendEmptyMessageDelayed(1, 5000L);
}
}
DataBinding在RecyclerView中的使用
同在RecyclerView中的Item也可以使用DataBinding,在onCreateViewHolder
中保存生成的Binding对象,在复用时,更新数据即可。并且可以在XML中设置ClickListener等事件。
RecyclerView的product_item.xml文件如下:
代码语言:javascript复制<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable name="product"
type="com.example.android.persistence.model.Product"/>
<variable name="callback"
type="com.example.android.persistence.ui.ProductClickCallback"/>
</data>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/product_item_min_height"
android:onClick="@{() -> callback.onClick(product)}"
android:orientation="horizontal"
android:layout_marginStart="@dimen/item_horizontal_margin"
android:layout_marginEnd="@dimen/item_horizontal_margin"
app:cardUseCompatPadding="true">
<TextView
android:id="@ id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/cd_product_name"
android:text="@{product.name}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginEnd="5dp"
android:text="@{@string/product_price(product.price)}"/>
</android.support.v7.widget.CardView>
</layout>
RecyclerAdapter中部分内容如下:
代码语言:javascript复制 @Override
public ProductViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ProductItemBinding binding = DataBindingUtil
.inflate(LayoutInflater.from(parent.getContext()), R.layout.product_item,
parent, false);
binding.setCallback(mProductClickCallback);
return new ProductViewHolder(binding);
}
@Override
public void onBindViewHolder(ProductViewHolder holder, int position) {
holder.binding.setProduct(mProductList.get(position));
holder.binding.executePendingBindings();
}
static class ProductViewHolder extends RecyclerView.ViewHolder {
final ProductItemBinding binding;
public ProductViewHolder(ProductItemBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
PS:在使用RecyclerView的时候,经常配合DiffUtil来进行数据的增量更新操作
注意事项
- 在使用数据的时候,属性必须是
public
或者提供了setter
,getter
方法,否则编译不过,无法生成Binding文件 - XML文件中禁止使用
merge
标签,可以使用include
标签,但是需要将变量传过去,否则数据无法传递。例如:
product_fragment.xml
...
<include
layout="@layout/product_item"
app:product="@{productViewModel.product}"/>
...
product_item.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable name="product"
type="com.example.android.persistence.model.Product"/>
<variable name="callback"
type="com.example.android.persistence.ui.ProductClickCallback"/>
</data>
...
参考链接
Data Binding Library DataBinding最全使用说明