LZ-Says:每一次的选择,都将面临更多的希望,加油,而今迈步重头跃。。。
前言
前段时间,完结了一篇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 style="@style/titleStyle" android:onTextChanged="@{presenter.onTextChanged}" /><TextView style="@style/contentStyle" android:text="展示数据更新-notifyPropertyChanged" /><TextView style="@style/titleStyle" android:text="@{classX.classNo}" /><TextView style="@style/titleStyle" android:text="@{classX.classNum}" /><TextView style="@style/titleStyle" 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 style="@style/titleStyle" android:text="@{missBean.missWho}" /><TextView style="@style/titleStyle" 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 style="@style/contentStyle" android:text="Observable Field" /><TextView style="@style/titleStyle" android:text="@{filedBean.filedName}" /><TextView style="@style/titleStyle" android:text='@{"年纪:"+filedBean.fileAge}' /><TextView style="@style/titleStyle" 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<String>" /></data>
这里需要注意,指定type时,ObservableArrayList类型里面不能包含<,而是通过 < ; 代替。
Step 2: 赋值
<TextView style="@style/contentStyle" android:text="ObservableArrayList Study" /><TextView style="@style/titleStyle" android:text="@{loveList.get(0)}" /><TextView style="@style/titleStyle" android:text="@{loveList.get(1)}" />
是不是很Easy,直接通过下标去访问即可。
Step 3: 查看演示效果
五、ObservableMap Study
Step 1: 布局添加引用
<data> <import type="android.databinding.ObservableMap" /> <variable name="loveMap" type="ObservableMap<String,String>" /></data>
Step 2: 赋值
<TextView style="@style/contentStyle" android:text="ObservableArrayMap Study" /><TextView style="@style/titleStyle" android:text='@{loveMap["name"]}' /><TextView style="@style/titleStyle" 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的使用:
定义布局文件,放置RecyclerView;
定义对应的item文件;
编写对应的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<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 style="@style/contentStyle" 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 style="@style/contentStyle" 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" style="@style/contentStyle" 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这样小白态度。。。等等,太多太多,心里真的很佩服~
前行之楷模~!!!
薇薇,一个超级超级超级努力、拼的漂亮妹子,努力程度,让我自愧不如。
。。。 。。。
身边大佬默默努力的例子太多太多。。。
最后让我们一起努力,也来个赶超鸡排大大,迎娶薇薇大佬(开玩笑,开玩笑~~~)~