一、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;
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}" />
先来看一波效果:
![](https://i-blog.csdnimg.cn/blog_migrate/2baa45c9e6fe4cb20839a66b4f2d67f0.gif)
有的小伙伴说了,这太麻烦了,我实体类属性字段有很多肿么办?一个个添加吗?
当然不。
二、notifyChange方式更新全部数据
基于上节,本次单独定义一个实体类,用于展示更新全部数据。
package com.hlq.databindingdemo.bean;
import android.databinding.BaseObservable;
import android.databinding.ObservableBoolean;
/**
* 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());
一起来看看效果:
![](https://i-blog.csdnimg.cn/blog_migrate/a92f8a1d0ba83e0cdfb462dee2fdbcb1.gif)
俩者区别在于:
如果仅仅是想更新部分属性字段,只需要在要更新的属性字段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;
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: 查看效果
![](https://i-blog.csdnimg.cn/blog_migrate/665d2a1caf151cc5dacadfe04340b484.jpeg)
有的小伙伴说了,那我如果想取值呢?怎么弄?
一张图包教包会!
![](https://i-blog.csdnimg.cn/blog_migrate/fc3b177b5fa4784d9f89c4f440d17662.jpeg)
Example Two:再来个稍稍复杂的玩玩
Step 1: 定义我们实体类
package com.hlq.databindingdemo.bean;
import android.databinding.ObservableBoolean;
import android.databinding.ObservableField;
import android.databinding.ObservableInt;
/**
* desc : Observable Field 实体类
*/
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: 查看演示效果
![](https://i-blog.csdnimg.cn/blog_migrate/dad70087ae1652addf53ce81324b977f.jpeg)
四、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: 查看演示效果
![](https://i-blog.csdnimg.cn/blog_migrate/79ef6b07c94abc7ec6f492871529711f.jpeg)
五、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: 查看效果演示图
![](https://i-blog.csdnimg.cn/blog_migrate/b486964c2785c37e5d83a978c0d39759.jpeg)
六、RecyclerView与DataBinding使用
目前的RecyclerView可谓火爆了半边天,试问,现在还是谁没用过?
先撸一波效果图~
![](https://i-blog.csdnimg.cn/blog_migrate/72efdfdc4da2de95dd622ff168c75bfa.gif)
首先,我们来回顾下,之前我们最普通关于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;
/**
* 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效果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/3fbc884c796d998ff0fcdf82798981e9.jpeg)
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;
/**
* 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;
/**
* 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;
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:运行一波,查看效果
![](https://i-blog.csdnimg.cn/blog_migrate/7c278d1d316a7c3cc3554b70ef987b8a.gif)
嗯,简单的玩完了,下面基于第六小节实现RecyclerView点击~
八、设置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);
}
基于第六小节修改完毕,运行走一波~
![](https://i-blog.csdnimg.cn/blog_migrate/addb57a082be12bf68c7cf7b5e1a2289.gif)
九、当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;
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);
查看效果:
![](https://i-blog.csdnimg.cn/blog_migrate/a9bdd3ada23cd045adfa1e040385ea80.gif)
十、十全十美,进阶收宫,来个注解完美告白
之前我们也多多少少使用了几个项目中常用的注解,而本文最后,拓展几个可能会用到的注解,来一个进阶篇完美谢幕~
先来俩个示例:
<?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>
如下效果:
![](https://i-blog.csdnimg.cn/blog_migrate/4679b0632bb997973dfffbb0cbf6e6b8.jpeg)
最后为大家提溜过来@BindingMethods以及@BindingMethod这俩个注解。
@BindingMethods以及@BindingMethod,这俩货是一对儿,你别想着拆散人俩,小心AS不放过你,那么具体他们使用以及场景又有哪儿些呢?
@BindingMethods,通常作为类的一个注解,它的作用,便是为其类或者实例添加新的技能;
@BindingMethod:苦逼执行者,旗下有三个小弟,如下:
type:给谁增加技能;
attribute :别人怎么激活这个技能;
method:这个技能被激活后会什么大招
首先,设置我们大招类:
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;
/**
* 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>
实体类:
package com.hlq.databindingdemo.bean;
public class VVBean {
public boolean vHeartBg;
public String vDesc;
public VVBean(boolean vHeartBg, String vDesc) {
this.vHeartBg = vHeartBg;
this.vDesc = vDesc;
}
}
最后,简单实例化一下:
mWordBind = DataBindingUtil.setContentView(this, R.layout.activity_word);
mWordBind.setVv(new VVBean(true, "程序猿,Oh,程序媛一枚,灵活的双手编织动人的世界~"));
看下效果~
GitHub查看地址
https://github.com/HLQ-Struggle/DataBindingDemo