手记

Android Study 之 如何通过Data Binding提升撸码逼格(进阶篇)

LZ-Says:每一次的选择,都将面临更多的希望,加油,而今迈步重头跃。。。

前言

前段时间,完结了一篇Data Binding前篇,地址如下:

Android Study 之 如何通过Data Binding提升撸码逼格(基础篇)

而今,我们一起来学习下,有关Data Binding进阶用法。

发车了,来来来

一、notifyPropertyChanged方式更新指定数据

首先,来简单介绍下Observable:

  • Observable 基于观察者模式更新;

  • 它的出现,便是为了解决当我们的实体发生改变时,UI即时刷新。

先来一个小例子:

  • 假设我们现在有一个User对象,当修改其中一个属性,使其引用的部分更新为修改后的值。

那么针对这个需求,我们使用Observable即可分分钟搞定。这里,大家可以简单理解为,这个就是负责数据更新~

下面来个Demo试试:

Step 1: 实体类继承BaseObservable

package com.hlq.databindingdemo.bean;import android.databinding.BaseObservable;import android.databinding.Bindable;import com.hlq.databindingdemo.BR;/**
 * author : HLQ
 * e-mail : 925954424@qq.com
 * time   : 2018/02/22
 * desc   : BaseObservable 学习了解
 * version: 1.0
 */public class ClassBean extends BaseObservable {    private String classNo;    private String classNum;    private String className;    public ClassBean(String className) {        this.className = className;
    }    public ClassBean(String className, String classNum) {        this.className = className;        this.classNum = classNum;
    }    public ClassBean(String classNo, String classNum, String className) {        this.classNo = classNo;        this.classNum = classNum;        this.className = className;
    }    @Bindable
    public String getClassNo() {        return classNo;
    }    public void setClassNo(String classNo) {        this.classNo = classNo;
    }    @Bindable
    public String getClassName() {        return className;
    }    public void setClassName(String className) {        this.className = className;
    }    @Bindable
    public String getClassNum() {        return classNum;
    }    public void setClassNum(String classNum) {        this.classNum = classNum;
    }
}

Step 2: 为字段设置notifyPropertyChanged

这里,老铁需要谨记一点即可:

想让谁更新,就给谁设置notifyPropertyChanged(BR.字段名)。

而设置的规则,简单如下:

例如,想为ClassBean中classNo设置更新,那么只需要在setClassNo中添加notifyPropertyChanged(BR.classNo);即可,其他同理。

那么,本小节演示所有字段设置更新,那么对应的代码段如下:

    public void setClassNo(String classNo) {        this.classNo = classNo;
        notifyPropertyChanged(BR.classNo);
    }    public void setClassName(String className) {        this.className = className;
        notifyPropertyChanged(BR.className);
    }    public void setClassNum(String classNum) {        this.classNum = classNum;
        notifyPropertyChanged(BR.classNum);
    }

而为了突出演示效果,这里添加一个EditText,用于在用户输入数据时,动态修改实体,从而进行UI即时刷新。

同样,也需要初始化以及设置事件,下面一起看看:

    private ActivityObservableBinding mBinding;    private ClassBean mClassBean = new ClassBean("001", "100", "A1T105");    @Override
    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_observable);
        mBinding.setClassX(mClassBean);
        mBinding.setPresenter(new Presenter());

    }    public class Presenter {        public void onTextChanged(CharSequence s, int start, int before, int count) {
            mClassBean.setClassNo("No:" + s);
            mClassBean.setClassNum("Num:" + s);
            mClassBean.setClassName("Name:" + s);
        }

    }

xml当中也只是简单的调用事件以及赋值,简单贴出部分代码:

<EditText
    
    android:onTextChanged="@{presenter.onTextChanged}" /><TextView
    
    android:text="展示数据更新-notifyPropertyChanged" /><TextView
    
    android:text="@{classX.classNo}" /><TextView
    
    android:text="@{classX.classNum}" /><TextView
    
    android:text="@{classX.className}" />

先来看一波效果:

有的小伙伴说了,这TMD太麻烦了,我实体类属性字段有很多肿么办?一个个添加吗?

当然不。身为程序猿猿,能偷懒,当然不傻傻干。瞧好吧您呐~

二、notifyChange方式更新全部数据

基于上节,本次单独定义一个实体类,用于展示更新全部数据。

package com.hlq.databindingdemo.bean;import android.databinding.BaseObservable;import android.databinding.ObservableBoolean;/**
 * author : HLQ
 * e-mail : 925954424@qq.com
 * time   : 2018/02/22
 * desc   : notifyChange 更新所有数据
 * version: 1.0
 */public class LoveBean extends BaseObservable {    private String youSelf;    private String mySelf;    private ObservableBoolean isTrueLove = new ObservableBoolean();    public LoveBean(String youSelf, String mySelf, boolean trueLove) {        this.youSelf = youSelf;        this.mySelf = mySelf;
        isTrueLove.set(trueLove);
    }    public String getYouSelf() {        return youSelf;
    }    public void setYouSelf(String youSelf) {        this.youSelf = youSelf;
    }    public String getMySelf() {        return mySelf;
    }    public void setMySelf(String mySelf) {        this.mySelf = mySelf;
    }    public ObservableBoolean getIsTrueLove() {        return isTrueLove;
    }    public void setIsTrueLove(boolean isTrueLove) {        this.isTrueLove.set(isTrueLove);
        notifyChange();
    }
}

这里需要注意,只需要为一个单独属性字段设置notifyChange即可实现所有数据均实现更新。

下面开始对应的初始化:

    private LoveBean mLoveBean = new LoveBean("Who are you", "H.L.Q.", true);
    ...
    mBinding.setLove(mLoveBean);
    ...
    mLoveBean.setYouSelf("Who are you?" + s);
    mLoveBean.setMySelf("H.L.Q." + s);
    mLoveBean.setIsTrueLove(!mLoveBean.getIsTrueLove().get());

一起来看看效果:

这里LZ再啰嗦一句,俩者区别在于:

  • 如果仅仅是想更新部分属性字段,只需要在要更新的属性字段set方法下添加notifyPropertyChanged(BR.属性字段名);

  • 如果是仅仅想更新全部属性字段,则随便在某个set的方法下添加notifyChange()。

当然,Data Binding的神奇之处还有很多,比如,它为我们提供了对应的一系列ObservableField,那么,下面,让我们一起去看看吧~

三、ObservableField Study

  • 有的小伙伴说了,忒麻烦,忒麻烦,我连get/set都不想搞,怎么破?

  • So easy~ 那都不叫事儿~

简单说一下ObservableField是什么鬼:

  • 首先,ObservableField是归属于Observable旗下,作用就是为了简化操作,避免你写多余的get/set,当然喽,优点并不止这些;

  • 其次,Observable旗下包含了很多类似ObservableField的家伙,例如:ObservableInt、ObservableBoolean等。

  • 如何使用呢?你怎么使用String、int等,就怎么使用这个。说白了,就是一个配套的家伙。

那么接下来,简单搞俩个Demo熟悉下使用:

Example One:先来个ObservableField练练手

Step 1: 定义实体类

import android.databinding.ObservableField;/**
 * author : HLQ
 * e-mail : 925954424@qq.com
 * time   : 2018/02/23
 * desc   : ObservableField 首战
 * version: 1.0
 */public class MissBean {    public final ObservableField<String> missWho = new ObservableField<>();    public final ObservableField<String> missYou = new ObservableField<>();

}

Step 2: 布局引用

引入命名空间。

<data>
    <variable
        name="missBean"
        type="com.hlq.databindingdemo.bean.MissBean" /></data>

设置对应值。

<TextView
    
    android:text="@{missBean.missWho}" /><TextView
    
    android:text="@{missBean.missYou}" />

Step 3: Activity中初始化 - 赋值

mMissBean = new MissBean();
mMissBean.missWho.set("在思念谁?");
mMissBean.missYou.set("在思念你~");
mBinding.setMissBean(mMissBean);

Step 4: 查看效果

有的小伙伴说了,那我如果想取值呢?怎么弄?

一张图包教包会~ 再不会打死你~!

Example Two:再来个稍稍复杂的玩玩

Step 1: 定义我们实体类

package com.hlq.databindingdemo.bean;import android.databinding.ObservableBoolean;import android.databinding.ObservableField;import android.databinding.ObservableInt;/**
 * author : HLQ
 * e-mail : 925954424@qq.com
 * time   : 2018/05/08
 * desc   : Observable Field 实体类
 * version: 1.0
 */public class ObservableFieldBean {    public ObservableField<String> filedName = new ObservableField<>();    public ObservableInt fileAge = new ObservableInt();    public ObservableBoolean fileStore = new ObservableBoolean();

}

可以看到,我们这次不仅仅使用了ObservableField,还有ObservableInt以及ObservableBoolean,用法是不是很Easy?

Step 2: 引入命名空间,赋值

<data>
    <variable
        name="filedBean"
        type="com.hlq.databindingdemo.bean.ObservableFieldBean" /></data>

接下来赋值:

<TextView
    
    android:text="Observable Field" /><TextView
    
    android:text="@{filedBean.filedName}" /><TextView
    
    android:text='@{"年纪:"+filedBean.fileAge}' /><TextView
    
    android:text='@{"结果为:"+filedBean.fileStore}' />

Step 3: 初始化

mFiledBean = new ObservableFieldBean();
mFiledBean.filedName.set("贺大大");
mFiledBean.fileAge.set(22);
mFiledBean.fileStore.set(true);
mFieldBinding.setFiledBean(mFiledBean);

Step 4: 查看演示效果

四、ObservableArrayList Study

Step 1: 引入命名空间,声明类型

<data>

    <import type="android.databinding.ObservableArrayList" />

    <variable
        name="loveList"
        type="ObservableArrayList&lt;String>" /></data>

这里需要注意,指定type时,ObservableArrayList类型里面不能包含<,而是通过 < ; 代替。

Step 2: 赋值

<TextView
    
    android:text="ObservableArrayList Study" /><TextView
    
    android:text="@{loveList.get(0)}" /><TextView
    
    android:text="@{loveList.get(1)}" />

是不是很Easy,直接通过下标去访问即可。

Step 3: 查看演示效果

五、ObservableMap Study

Step 1: 布局添加引用

<data>

    <import type="android.databinding.ObservableMap" />

    <variable
        name="loveMap"
        type="ObservableMap&lt;String,String>" /></data>

Step 2: 赋值

<TextView
    
    android:text="ObservableArrayMap Study" /><TextView
    
    android:text='@{loveMap["name"]}' /><TextView
    
    android:text='@{loveMap["age"]}' />

Step 3: 初始化

ObservableMap<String, String> testMap = new ObservableArrayMap<>();
testMap.put("name", "贺大宝,心情不美丽");
testMap.put("age", "22的年龄,啧啧");
mFieldBinding.setLoveMap(testMap);

Step 4: 查看效果演示图

六、RecyclerView与DataBinding使用

目前的RecyclerView可谓火爆了半边天,试问,现在还是谁没用过?

先撸一波效果图~

首先,我们来回顾下,之前我们最普通关于RecyclerView的使用:

  1. 定义布局文件,放置RecyclerView;

  2. 定义对应的item文件;

  3. 编写对应的Java Bean以及Adapter,其中Adapter中需要单独编写ViewHolder类,且此类需继承RecyclerView.ViewHolder。

大概简单来讲就是以上三个步骤,那么我们根据以上三步骤并结合当前Data Binding去一步步学习掌握如何二者结合使用。

Step 1: 定义布局文件

这里需要注意以下几点:

  • 引入所需Java Bean以及我们的ObservableArrayList;

  • 通过app:data属性将我们的List传递到RecyclerView中。(注意使用app:data需要导入命名空间,并且RecyclerView本身并不提供setData的api,所以我们只能造一个。)

上面说到,由于RecyclerView本身并不提供setData方式,所以我们需要自己造一个,那么有的小伙伴就会问了,我之前没使用Data Binding的时候,也不需要setData呀。其实这个东西大家可以简单理解为,它就是一个桥接的作用,将传递过来的数据与RecyclerView绑定,也就是真正让RecyclerView拿到传递的数据。 (当然,关于这块如果有更好更通俗的解释,欢迎拍砖~)

定义桥接类如下:

package com.hlq.databindingdemo.util;import android.databinding.BindingAdapter;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import com.hlq.databindingdemo.adapter.ShowLoveHistoryAdapter;import com.hlq.databindingdemo.bean.LoveBean;import java.util.List;/**
 * author : HLQ
 * e-mail : 925954424@qq.com
 * time   : 2018/02/24
 * desc   : 桥接ReccyclerView与Data Binding
 * version: 1.0
 */public class BindUtils {    @BindingAdapter("data")    public static void setShowLoveHistoryData(RecyclerView recyclerView,
                                              List<LoveBean> loveList) {
        recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
        recyclerView.setAdapter(new ShowLoveHistoryAdapter(recyclerView.getContext(), loveList));
    }

}

而我们放置RecyclerView布局如下:

<?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"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <import type="com.hlq.databindingdemo.bean.LoveBean" />

        <import type="android.databinding.ObservableArrayList" />

        <variable
            name="loveList"
            type="ObservableArrayList&lt;LoveBean>" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.hlq.databindingdemo.activity.RecyclerViewActivity">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/showLove"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:data="@{loveList}" />

    </LinearLayout></layout>

Step 2: 定义对应的item文件

这里我们简单思考下:

既然是Adapter形式,那么传递到Item中当然是一个实体类形式,我们只需要将每次遍历得到的实体依次赋给item所需内容即可。

如演示图所示,这里为了方便就不单独定义实体类了,直接使用原有的,如下:

<?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>

        <variable
            name="love"
            type="com.hlq.databindingdemo.bean.LoveBean" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="15dp"
            android:background="@drawable/ic_launcher_round" />

        <TextView
            
            android:layout_centerVertical="true"
            android:layout_marginTop="15dp"
            android:layout_toRightOf="@id/icon"
            android:text="@{love.youSelf}"
            tools:text="姓名" />

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_below="@id/icon"
            android:background="#fff" />

    </RelativeLayout></layout>

item效果如下:

Step 3: 编写Adapter

package com.hlq.databindingdemo.adapter;import android.content.Context;import android.databinding.DataBindingUtil;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.ViewGroup;import com.hlq.databindingdemo.R;import com.hlq.databindingdemo.bean.LoveBean;import com.hlq.databindingdemo.databinding.ItemLoveHistoryShowBinding;import com.hlq.databindingdemo.holder.ShowLoveHistoryHolder;import java.util.List;/**
 * author : HLQ
 * e-mail : 925954424@qq.com
 * time   : 2018/02/24
 * desc   : RecyclerView与DataBinding使用
 * version: 1.0
 */public class ShowLoveHistoryAdapter extends RecyclerView.Adapter<ShowLoveHistoryHolder> {    private Context mContext;    private List<LoveBean> mLoveList;    public ShowLoveHistoryAdapter(Context mContext, List<LoveBean> mLoveList) {        this.mContext = mContext;        this.mLoveList = mLoveList;
    }    @Override
    public ShowLoveHistoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        ItemLoveHistoryShowBinding binding = DataBindingUtil.inflate(
                LayoutInflater.from(mContext),
                R.layout.item_love_history_show,
                parent, false);        return new ShowLoveHistoryHolder(binding);
    }    @Override
    public void onBindViewHolder(ShowLoveHistoryHolder holder, int position) {
        holder.getBinding().setLove(mLoveList.get(position));        // 立即刷新界面,防止列表更新不及时,导致数据错乱
        holder.getBinding().executePendingBindings();
    }    @Override
    public int getItemCount() {        return mLoveList == null ? 0 : mLoveList.size();
    }

}

这里为了方便,单独将ViewHolder抽取出来。

package com.hlq.databindingdemo.holder;import android.support.v7.widget.RecyclerView;import com.hlq.databindingdemo.databinding.ItemLoveHistoryShowBinding;/**
 * author : HLQ
 * e-mail : 925954424@qq.com
 * time   : 2018/02/24
 * desc   : RecyclerView 所需Holder
 * version: 1.0
 */public class ShowLoveHistoryHolder extends RecyclerView.ViewHolder {    private ItemLoveHistoryShowBinding binding;    public ShowLoveHistoryHolder(ItemLoveHistoryShowBinding binding) {        super(binding.getRoot());        this.binding = binding;
    }    public ItemLoveHistoryShowBinding getBinding() {        return binding;
    }    public void setBinding(ItemLoveHistoryShowBinding binding) {        this.binding = binding;
    }

}

Step 4: 初始化

package com.hlq.databindingdemo.activity;import android.databinding.DataBindingUtil;import android.databinding.ObservableArrayList;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import com.hlq.databindingdemo.R;import com.hlq.databindingdemo.bean.LoveBean;import com.hlq.databindingdemo.databinding.ActivityRecyclerViewBinding;/**
 * author : HLQ
 * e-mail : 925954424@qq.com
 * time   : 2018/02/23
 * desc   : RecyclerView与DataBinding使用
 * version: 1.0
 */public class RecyclerViewActivity extends AppCompatActivity {    @Override
    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        ActivityRecyclerViewBinding binding =
                DataBindingUtil.setContentView(this, R.layout.activity_recycler_view);
        ObservableArrayList<LoveBean> loveList = new ObservableArrayList<>();        for (int i = 0; i < 30; i++) {
            loveList.add(new LoveBean("youSelf" + i, "mySelf" + i, true));
        }
        binding.setLoveList(loveList);
    }
}

嗯,小手一点,运行一波,走起~

七、老方式设置RecyclerView点击事件

来来来,Come on,我们一起回顾下当年如何简单有效实现RecyclerView并为其添加点击事件:

  • Activity中摆放好RecyclerView;

  • 初始化,编写item以及对于Adapter、ViewHolder;

  • 当然,不要忘记在adapter中设置事件,Activity中回调。

那么基于以上路子,我们一块快速简单有效的撸一波有关结合Data Binding的用法吧~

Step 1:摆放RecyclerView

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".activity.NormalRecyclerViewActivity">

        <TextView
            
            android:text="换种姿势玩转RecyclerView" />

        <android.support.v7.widget.RecyclerView
            android:id="@+id/showList"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout></layout>

Step 2:摆放Item_layout

这里需要注意,因为我们是结合Data Binding,而真正落实到Item时,仅仅是一个Model,也就是我们最终的实体类。
So,在此,我们需要将我们的Model传递进去。

<?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>

        <variable
            name="user"
            type="com.hlq.databindingdemo.bean.UserBean" />
    </data>

    <LinearLayout
        android:id="@+id/parent_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/item_list"
            
            android:text="@{user.userName}"
            tools:text="item测试数据" />

        <View
            android:layout_width="match_parent"
            android:layout_height="2dp"
            android:background="#fff" />

    </LinearLayout></layout>

Step 3:编写Adapter

这里简单总结下,看看我们的Adapter中需要落实些什么鬼~!

  • 继承RecyclerView.Adapter,实现方法添加ViewHolder并继承RecyclerView.ViewHolder,而我们这次的Holder只需要Binding即可;

  • 传递Model,刷新RecyclerView;

  • 设置interface onItemClickListener;

嗯,基于以上三点,开始撸本次代码:

package com.hlq.databindingdemo.adapter;import android.content.Context;import android.databinding.DataBindingUtil;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import com.hlq.databindingdemo.R;import com.hlq.databindingdemo.bean.UserBean;import com.hlq.databindingdemo.databinding.ItemShowListBinding;import java.util.List;/**
 * author : HLQ
 * e-mail : 925954424@qq.com
 * time   : 2018/05/09
 * desc   :
 * version: 1.0
 */public class ShowListAdapter extends RecyclerView.Adapter<ShowListAdapter.ViewHolder> {    private Context mContext;    private List<UserBean> mUserBeanList;    private onItemClickListener mOnItemClickListener;    private ItemShowListBinding mListBinding;    public ShowListAdapter(Context context, List<UserBean> userBeanList) {        this.mContext = context;        this.mUserBeanList = userBeanList;
    }    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        mListBinding = DataBindingUtil.inflate(LayoutInflater.from(mContext), R.layout.item_show_list, parent, false);        return new ViewHolder(mListBinding);
    }    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {        // 传递Model
        holder.mListBinding.setUser(mUserBeanList.get(position));        // 刷新RecyclerView
        holder.mListBinding.executePendingBindings();        // 设置事件 只需要传递当前item所需Model(Java Bean)即可
        if (mOnItemClickListener != null) {
            holder.mListBinding.parentList.setOnClickListener(new View.OnClickListener() {                @Override
                public void onClick(View v) {
                    mOnItemClickListener.onItemClickListener(mUserBeanList.get(position));
                }
            });
        }
    }    @Override
    public int getItemCount() {        return mUserBeanList.size();
    }    class ViewHolder extends RecyclerView.ViewHolder {        private ItemShowListBinding mListBinding;        public ViewHolder(ItemShowListBinding listBinding) {            super(listBinding.getRoot());            this.mListBinding = listBinding;
        }
    }    public void setOnItemClickListener(onItemClickListener onItemClickListener) {        this.mOnItemClickListener = onItemClickListener;
    }    public interface onItemClickListener {        void onItemClickListener(UserBean userBean);

    }

}

Step 4:初始化RecyclerView、数据以及设置事件处理

    private ActivityNormalRecyclerViewBinding mNormalBinding;    private ShowListAdapter mShowListAdapter;    private List<UserBean> mShowList;    @Override
    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        mNormalBinding = DataBindingUtil.setContentView(this, R.layout.activity_normal_recycler_view);
        initData();
        initRecyclerViewSetting();
    }    private void initData() {
        mShowList = new ArrayList<>();        for (int i = 0; i < 30; i++) {
            mShowList.add(new UserBean("贺大大" + i));
        }
    }    private void initRecyclerViewSetting() {
        mNormalBinding.showList.setLayoutManager(new LinearLayoutManager(this));
        mShowListAdapter = new ShowListAdapter(this, mShowList);
        mShowListAdapter.setOnItemClickListener(new ShowListAdapter.onItemClickListener() {            @Override
            public void onItemClickListener(UserBean userBean) {
                Toast.makeText(NormalRecyclerViewActivity.this, "点击了:" + userBean.getUserName(), Toast.LENGTH_SHORT).show();
            }
        });
        mNormalBinding.showList.setAdapter(mShowListAdapter);
    }

Step 5:运行一波,查看效果

嗯,简单的玩完了,下面基于第六小节实现RecyclerView点击~

八、来个装B的方式设置RecyclerView点击事件

既然本小节基于第六小节实现item点击,那么多余的部分LZ这里不再叙述,这里着重讲几点思路:

  • 由于我们的Adapter被单独抽取到BindUtil中进行初始化,那么对应的,我们也得在BindUtil初始化Adapter为其设置事件并进行后续处理;

  • 而对应的Adapter则主要在Bind数据时,单独为Icon设置点击事件,其它暂时不需要改动。

当然为了便于接收者处理,这里我们的事件直接传递Model,Adapter关键代码如下:

    @Override
    public void onBindViewHolder(ShowLoveHistoryHolder holder, final int position) {
        holder.getBinding().setLove(mLoveList.get(position));        // 立即刷新界面,防止列表更新不及时,导致数据错乱
        holder.getBinding().executePendingBindings();        // 设置事件
        if (mOnItemClickListener != null) {
            holder.getBinding().icon.setOnClickListener(new View.OnClickListener() {                @Override
                public void onClick(View v) {
                    mOnItemClickListener.OnItemClickListener(mLoveList.get(position));
                }
            });
        }
    }    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {        this.mOnItemClickListener = onItemClickListener;
    }    public interface OnItemClickListener {        void OnItemClickListener(LoveBean loveBean);

    }

而对应的BindUtils中则只需要设置事件实例以及处理事件即可:

    @BindingAdapter("data")    public static void setShowLoveHistoryData(final RecyclerView recyclerView,
                                              List<LoveBean> loveList) {
        recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
        ShowLoveHistoryAdapter adapter = new ShowLoveHistoryAdapter(recyclerView.getContext(), loveList);
        adapter.setOnItemClickListener(new ShowLoveHistoryAdapter.OnItemClickListener() {            @Override
            public void OnItemClickListener(LoveBean loveBean) {
                Toast.makeText(recyclerView.getContext(), "点击了:" + loveBean.getYouSelf(), Toast.LENGTH_SHORT).show();
            }
        });
        recyclerView.setAdapter(adapter);
    }

基于第六小节修改完毕,运行走一波~

九、当Data Binding遇到ImageView

在我们的上面有关RecyclerView时,大家注意到一个@BindingAdapter("data")么?

这个东西是什么?

简单可以理解为:

@BindingAdapter()类似一个桥梁,主要负责数据到Data Binding层,同样,牛掰的地方也在于,可以为你想使用的控件硬生生加个特异功能~

好比我们的RecyclerView原本没有接收数据的属性,但是,薇薇改动后,就这么神器的有了~~~

同理,依照上面如何为RecyclerView添加Data,下面先来撸一个有关ImageView的Util:

package com.hlq.databindingdemo.util;import android.databinding.BindingAdapter;import android.graphics.drawable.Drawable;import android.widget.ImageView;import com.bumptech.glide.Glide;/**
 * author : HLQ
 * e-mail : 925954424@qq.com
 * time   : 2018/05/16
 * desc   : Fuck Code Fuck Fuck Fuck
 * version: 1.0
 */public class ImageUtils {    @BindingAdapter("imageResource")    public static void setImageResource(
            ImageView imageView,            int imgID) {
        imageView.setImageResource(imgID);
    }    @BindingAdapter("imageDrawable")    public static void setImageDrawable(
            ImageView imageView,
            Drawable imgDrawable) {
        imageView.setImageDrawable(imgDrawable);
    }    @BindingAdapter({"defaultImg", "loadingImg", "errorImg"})    public static void setImageForGlide(
            ImageView imageView,
            Drawable defaultImg,
            String imageAddress,
            Drawable errorImg) {
        Glide.with(imageView.getContext())
                .load(imageAddress)
                .error(errorImg)
                .placeholder(defaultImg)
                .into(imageView);
    }


}

布局里面就很easy咯(不过这里要注意,调用者顺序以及类型需要统一,不然真的就GG了~):

<?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"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="image"
            type="com.hlq.databindingdemo.bean.ImageBean" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        tools:context=".activity.ImageViewActivity">

        <ImageView
            android:layout_width="80dp"
            android:layout_height="80dp"
            app:imageResource="@{image.imageResID}" />

        <ImageView
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:layout_marginTop="15dp"
            app:imageDrawable="@{@drawable/hlq_gzh}" />

        <ImageView
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:layout_marginTop="15dp"
            app:defaultImg="@{@drawable/hlq_gzh}"
            app:errorImg="@{@drawable/ic_launcher_round}"
            app:loadingImg="@{image.imgUrl}" />

    </LinearLayout></layout>

而对应Activity中则很easy,初始化即可:

mImageBinding = DataBindingUtil.setContentView(this, R.layout.activity_image_view);
ImageBean imageBean = new ImageBean();
imageBean.imageResID = R.drawable.ic_launcher_round;
imageBean.imgUrl = "http://d.hiphotos.baidu.com/image/pic/item/6159252dd42a2834171827b357b5c9ea14cebfcf.jpg";
mImageBinding.setImage(imageBean);

查看效果:

十、十全十美,进阶收宫,来个注解完美告白

之前我们也多多少少使用了几个项目中常用的注解,而本文最后,拓展几个可能会用到的注解,来一个进阶篇完美谢幕~

先来俩个恶搞薇薇的示例:

<?xml version="1.0" encoding="utf-8"?><layout>

    <data>

        <variable
            name="vv"
            type="com.hlq.databindingdemo.bean.VVBean" />
    </data>

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".activity.WordActivity">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="15dp"
            android:background="@{vv.vHeartBg ? @color/c_yellow : @color/c_while}"
            android:gravity="center"
            android:padding="15dp"
            android:text="VV内心颜色如同背景色"
            android:textColor="#000" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="15dp"
            android:background="@color/colorAccent"
            android:gravity="center"
            android:padding="15dp"
            android:text="@{vv.vDesc}"
            android:textColor="#000" />


    </LinearLayout></layout>

如下效果:

有的伙计说,你不怕薇薇怼你?

鸡排我大哥~~~啦啦啦

扯犊子完成,最后为大家提溜过来@BindingMethods以及@BindingMethod这俩个注解,玩完睡觉,正好想想高级篇如何实现,不知不觉,一周又要过去了。。。

@BindingMethods以及@BindingMethod,这俩货是一对儿,你别想着拆散人俩,小心AS不放过你,那么具体他们使用以及场景又有哪儿些呢?

  • @BindingMethods,通常作为类的一个注解,它的作用,便是为其类或者实例添加新的技能;

  • @BindingMethod:苦逼执行者,旗下有三个小弟,如下:

    • attribute :别人怎么激活这个技能;

    • method:这个技能被激活后会什么大招,enmmm,比如虐薇薇,嗯,对,虐薇薇~

    • type:给谁增加技能;

总扯犊子不干正事儿,小心被人说空有其表,华而不实:

首先,设置我们大招类:

package com.hlq.databindingdemo.weight;import android.content.Context;import android.databinding.BindingMethod;import android.databinding.BindingMethods;import android.support.annotation.Nullable;import android.support.v7.widget.AppCompatTextView;import android.util.AttributeSet;import android.widget.Toast;/**
 * author : HLQ
 * e-mail : 925954424@qq.com
 * time   : 2018/05/17
 * desc   : 大招类 主动激活 则将薇薇轰上天~!!!
 * version: 1.0
 */@BindingMethods(        @BindingMethod(
                type = AppCompatTextView.class, // 目标
                attribute = "activation", // 激活方式
                method = "setActivation" // 激活后链接自动释放大招 
        )
)public class VVBiuView extends AppCompatTextView {    public VVBiuView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);
    }    /**
     * 主动激活技能,将薇薇轰上天~
     *
     * @param msg
     */
    public void setActivation(String msg) {
        Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
    }

}

大招蓄势待发,下面开始布置环境(LZ这里顽皮一波):

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="vv"
            type="com.hlq.databindingdemo.bean.VVBean" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".activity.WordActivity">

        <com.hlq.databindingdemo.weight.VVBiuView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="15dp"
            android:background="@color/colorPrimary"
            android:padding="15dp"
            android:text="我是隐藏大招~"
            app:activation="@{vv.vDesc}"/>

    </LinearLayout></layout>

有的伙伴说,哎那谁,你TMD的实体类哪儿去了?

MD,给你~!!!

package com.hlq.databindingdemo.bean;/**
 * author : HLQ
 * e-mail : 925954424@qq.com
 * time   : 2018/05/17
 * desc   : 薇薇是个二货~!!!
 * version: 1.0
 */public class VVBean {    public boolean vHeartBg;    public String vDesc;    public VVBean(boolean vHeartBg, String vDesc) {        this.vHeartBg = vHeartBg;        this.vDesc = vDesc;
    }

}

emmmm,最后,简单实例化一下:

mWordBind = DataBindingUtil.setContentView(this, R.layout.activity_word);
mWordBind.setVv(new VVBean(true, "程序猿,Oh,程序媛一枚,灵活的双手编织动人的世界~"));

enmm,冒着被薇薇打死的风险撸完了,看下效果~

LZ比比会儿

有时候,总觉得自己很努力,但是未曾发现,那些比你优秀的人同样在努力。

鸡排,对技术的严谨,对成果的执着,对LZ这样小白态度。。。等等,太多太多,心里真的很佩服~

前行之楷模~!!!

薇薇,一个超级超级超级努力、拼的漂亮妹子,努力程度,让我自愧不如。

。。。 。。。

身边大佬默默努力的例子太多太多。。。

最后让我们一起努力,也来个赶超鸡排大大,迎娶薇薇大佬(开玩笑,开玩笑~~~)~

GitHub查看地址

https://github.com/HLQ-Struggle/DataBindingDemo

原文链接:http://www.apkbus.com/blog-904057-77832.html

0人推荐
随时随地看视频
慕课网APP