Android开发Android开发经验谈程序员

2017-9-5(dataBinding使用)

2017-09-05  本文已影响72人  721d739b6619

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布局文件写法

以<layout></layout>标签为根;到时候它会自动生成一个继承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>

<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"/>

非自定义属性,注意区分

自己写了个Demo以便遗忘:

databindingdemo

上一篇下一篇

猜你喜欢

热点阅读