2017-9-5(dataBinding使用)

257 阅读4分钟

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.png

xml布局文件写法

以标签为根;到时候它会自动生成一个继承ViewDataBinding类的类;如布局文件名为main_layout,生成类名为:MainLayoutBinding

Paste_Image.png

View与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>

标签是为了关联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.activitydatabinding_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"/>

非自定义属性,注意区分

自己写了个Demo以便遗忘:

databindingdemo