DataBinding类似于ButterKnife,可以将数据结构与XML绑定,节省了很多Activity中UI的代码,比如说findViewById
等。也可以提升APP性能,帮助避免内存泄露以及空指针的问题。
app
模块的build.gradle
中添加DataBinding配置:android {
...
dataBinding {
enabled = true
}
}
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
,而不是具体的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文件
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);
}
}
同在RecyclerView中的Item也可以使用DataBinding,在onCreateViewHolder
中保存生成的Binding对象,在复用时,更新数据即可。并且可以在XML中设置ClickListener等事件。
RecyclerView的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>
<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中部分内容如下:
@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文件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>
...