Data binding 在2015年7月发布的Android Studio v1.3.0 版本上引入,
在2016年4月Android Studio v2.0.0 上正式支持。
目前为止,Data Binding 已经支持双向绑定了。
Data Binding 是一个support库,最低支持到Android 2.1(API Level 7+)。
本篇主要记录databinding项目中经常使用的地方。其他方面可以参照此文本人觉得写得很详细,我也是参照它的:
Android-Data-Binding-系列-一-详细介绍与使用
引入databanding
Paste_Image.pngxml布局文件写法
以<layout></layout>标签为根;到时候它会自动生成一个继承ViewDataBinding类的类;如布局文件名为main_layout,生成类名为:MainLayoutBinding
Paste_Image.pngView与Bean之间数据绑定
布局文件是这样的:
<?xml version="1.0" encoding="utf-8"?>
<!-- 下面的命名空间需要写,不然下面android属性都不会显示 -->
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="user"
type="com.wyman.databindingdemo.databindingbean.DataBindingBean"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/userName_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{user.name ?? `Default name`}"
/>
<TextView
android:id="@+id/userAge_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{user.age ?? `Deafault age`}"
/>
<TextView
android:id="@+id/userDes_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{user.des ?? `Default des`}"
/>
<Button
android:id="@+id/databindingbean_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="更改bean"
android:onClick="doClick"
/>
</LinearLayout>
</layout>
<data></data>标签是为了关联java bean,DataBindingBean类就是这个bean,name是在布局文件上的名称;view与bean关联通过"@{user.name}";意思是bean的某个属性;
"@{user.des ?? Default des
}"这种写法的意思是当user.des为null时默认为Defauult des
再看看bean的写法
public class DataBindingBean implements Serializable{
private String name;
private String age;
private String des;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
}
没有什么特别与以前写的一模一样,你也可以不实现Serializable;
看看如何进行数据绑定
public class DataBindingBeanActivity extends AppCompatActivity {
private ActivityDataBindingBeanBinding binding;
private DataBindingBean bean;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_data_binding_bean);
binding = DataBindingUtil.setContentView(this,R.layout.activity_data_binding_bean);
bean = new DataBindingBean();
bean.setName("testName");
bean.setAge("testAge");
bean.setDes("testDes");
//这样将view与bean进行绑定
binding.setUser(bean);
binding.databindingbeanButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeBean(bean);
}
});
}
/**
* 这里尝试改变bean,看textview随之改变
* */
private void changeBean(DataBindingBean bean) {
bean.setDes("change testDes");
bean.setName(null);
binding.setUser(bean);
}
}
ActivityDataBindingBeanBinding是系统自动生成的layout布局文件的一个继承自ViewDataBinding 的类。
通过 DataBindingUtil.setContentView(this,R.layout.activity_data_binding_bean);就可以获取到该对象。为什么要该对象呢?往下看:
主要都是通过该类进行数据绑定更改数据的。
binding.setUser(bean);
这里就是实现了view与bean之间的关联;
看看第二种通过BaseObservable监听
bean部分
public class DataBindingRecyclerBean extends BaseObservable{
private String dataName;
private String dataDate;
private String dataMsg;
@Bindable
public String getDataName() {
return dataName;
}
public void setDataName(String dataName) {
this.dataName = dataName;
notifyPropertyChanged(BR.dataName);
}
@Bindable
public String getDataDate() {
return dataDate;
}
public void setDataDate(String dataDate) {
this.dataDate = dataDate;
notifyPropertyChanged(BR.dataDate);
}
@Bindable
public String getDataMsg() {
return dataMsg;
}
public void setDataMsg(String dataMsg) {
this.dataMsg = dataMsg;
notifyPropertyChanged(BR.dataMsg);
}
}
这里和上面的bean不同继承了BaseObservable,get方法前面有个注解@Bindable,set方法多了notifyPropertyChange(BR.dataName)
注意,是先有@Bindable后有notifyPropertyChange(BR.dataName)的,不然BR后面的属性是不会生成
布局文件没有什么特别
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="bean"
type="com.wyman.databindingdemo.databindingrecyclerview.DataBindingRecyclerBean"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/listPreferredItemHeight"
android:orientation="vertical"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingStart="?android:attr/listPreferredItemPaddingStart">
<TextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@{bean.dataName}"
android:textAppearance="?attr/textAppearanceListItem"/>
<TextView
android:id="@+id/text2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignStart="@id/text1"
android:layout_below="@id/text1"
android:text="@{bean.dataDate}"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"/>
<TextView
android:id="@+id/text3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignStart="@id/text2"
android:layout_below="@id/text1"
android:text="@{bean.dataMsg}"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"/>
</LinearLayout>
</layout>
再看看adapter
这里只贴绑定部分,基本上与上种方法一样
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//将数据与itemview绑定
holder.mItemBinding.setBean(mList.get(position));
}
最后一种@BindAdapter
一开始一看我还是以为与adapter相关联的,原来非也。直接黏代码
/**
* 注解 @BindAdapter 用法
*/
public class BindAdapterActivity extends AppCompatActivity {
private BindadapterLayoutBinding mBinding;
private static Context mContext;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.bindadapter_layout);
mContext = this;
//往 testName 注值
mBinding.setTestName("testName");
}
// 使用注解,无需手动调用此函数
@BindingAdapter({"testName","error"})
public static void testBinddingAdapter(View view,String testName,String error){
String text = "";
if(TextUtils.isEmpty(testName)){
text = error;
} else {
text = testName;
}
Toast.makeText(mContext,text,Toast.LENGTH_LONG).show();
}
boolean flag = false;
public void onClick(View view){
if(flag){
mBinding.setTestName(null);
flag = false;
} else {
mBinding.setTestName("bindadapter");
flag = true;
}
}
}
<?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"
>
<data>
<variable
name="testName"
type="String"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- 当url存在时,会自动调用注解方法,即Utils中得loadImage()-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
app:testName="@{testName}"
app:error="@{@string/app_name}"
/>
<!-- 此处不能使用mipmap,会编译不过
-->
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="更改BindAdapter"
android:onClick="onClick"
/>
</LinearLayout>
</layout>
这里其实先看布局文件看TextView标签,多了两个自定义属性,是在注解@BindAdapter使用到的,就在那里注解标注写明。
看看app:testName="@{testName}",@花括号里面的testName是对应上面data标签的testName的,说明这里传入是String类型,对于java里面lang包里面可以省略全类名。
再看看@BindAdapter
@BindingAdapter({"testName","error"})里面的testName和error就是对应刚刚说的两个属性的,刚方法是系统自动调用到,当数据改变就会调用到该方法.
mBinding.setTestName("testName");该方法的出现是由于布局文件的data标签里面的
<variable
name="testName"
type="String"/>
非自定义属性,注意区分
网友评论