這一章,為大家?guī)?lái)利用Data Binding為RecyclerView填充數(shù)據(jù)。這里的難點(diǎn)和核心點(diǎn)就是RecyclerView中Adapter的實(shí)現(xiàn)。這里以RecyclerView多布局的情況來(lái)講解。
1、一般情況下,我們RecyclerView多布局的Adapter大致如下
public class MultiItemAdapter extends BaseBindRecyclerViewAdapter<IBaseBindingAdapterBean> {
public MultiItemAdapter(Context context, List<IBaseBindingAdapterBean> mList) {
super(context, mList);
}
@Override
public int getItemViewType(int position) {
return mList.get(position).getItemViewType();
}
@Override
public RecyclerView.ViewHolder onCreateMyViewHolder(ViewGroup parent, int viewType) {
}
@Override
public void onBindMyViewHolder(RecyclerView.ViewHolder holder, int position) {
}
class FruitViewHolder extends RecyclerView.ViewHolder {
public FruitViewHolder(View itemView) {
super(itemView);
}
}
class TextViewHolder extends RecyclerView.ViewHolder {
public TextViewHolder(View itemView) {
super(itemView);
}
}
但是用了DataBinding以后,主要有3個(gè)地方發(fā)生了變化,ViewHolder, onCreateViewHolder,onBindMyViewHolder,下面就依次講解。
1.編寫(xiě)Viewholder
這里我的RecyclerView有兩種布局,并且布局全部是用databinding編寫(xiě)的,布局就先不展示了,demo里面有
class FruitViewHolder extends RecyclerView.ViewHolder {
private ItemFruitBinding binding;
public ItemFruitBinding getBinding() {
return binding;
}
public FruitViewHolder(ItemFruitBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
這里發(fā)生了一點(diǎn)變化,1.構(gòu)造函數(shù)的參數(shù)不再是你item布局對(duì)應(yīng)的View對(duì)象了,而是變成了你item布局對(duì)應(yīng)的ViewDataBinding對(duì)象,這個(gè)名字是和你item布局的名字相關(guān)的,我這里的item是item_fruit.xml。2.里面寫(xiě)了一個(gè)getBinding的方法,方便獲取binding對(duì)象。另一個(gè)ViewHolder也是類似的,大家也應(yīng)該發(fā)現(xiàn)了,ViewHolder里面不需要其他操作,以前的那些findViewById去獲取控件對(duì)象都不用了,因?yàn)閕tem布局里面已經(jīng)和數(shù)據(jù)綁定了。
2.重寫(xiě)onCreateViewHolder(ViewGroup parent, int viewType)
這里根據(jù)返回的viewType布局類型來(lái)創(chuàng)建不同的ViewHolder,viewType為getItemViewType(int position)方法返回的值:
@Override
public RecyclerView.ViewHolder onCreateMyViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case R.layout.item_fruit:
ItemFruitBinding itemFruitBinding = DataBindingUtil.inflate(inflater, R.layout.item_fruit, parent, false);
return new FruitViewHolder(itemFruitBinding);
case R.layout.item_text:
ItemTextBinding itemTextBinding = DataBindingUtil.inflate(inflater, R.layout.item_text, parent, false);
return new TextViewHolder(itemTextBinding);
default:
ItemFruitBinding binding = DataBindingUtil.inflate(inflater, R.layout.item_fruit, parent, false);
return new FruitViewHolder(binding);
}
}
這里和以前的區(qū)別就是返回ViewHolder對(duì)象的方式不同了,是通過(guò)DataBindingUtil.inflate()的方式來(lái)獲取,因?yàn)閂iewHolder需要傳入的參數(shù)是ViewDataBinding對(duì)象。
這里還要先給大家看看,我這個(gè)viewType是怎么來(lái)的
@Override
public int getItemViewType(int position) {
return mList.get(position).getItemViewType();
}
mList.get(position)得到的就是當(dāng)前位置的Item對(duì)應(yīng)的JavaBean對(duì)象,而這些item對(duì)應(yīng)的Bean都去實(shí)現(xiàn)一個(gè)接口IBaseBindingAdapterItem
public interface IBaseBindingAdapterItem {
//獲取Item的類型
int getItemViewType();
}
然后Bean對(duì)象就會(huì)實(shí)現(xiàn)這個(gè)getItemViewType()方法,返回值就是這個(gè)Bean對(duì)應(yīng)的Item布局的layout的ID,
public class FruitItem extends BaseObservable implements IBaseBindingAdapterItem {
private int picId; //圖片的ID
private String describe; //描述
public FruitItem(int picId, String describe) {
this.picId = picId;
this.describe = describe;
}
@Bindable
public int getPicId() {
return picId;
}
public void setPicId(int picId) {
this.picId = picId;
notifyPropertyChanged(BR.picId);
}
@Bindable
public String getDescribe() {
return describe;
}
public void setDescribe(String describe) {
this.describe = describe;
notifyPropertyChanged(BR.describe);
}
@Override
public int getItemViewType() {
return R.layout.item_fruit;
}
}
不懂BaseObservable?那是因?yàn)檫@里我用了雙向綁定,還不懂什么是雙向綁定的童鞋,可以看我的另一篇文章。
3.onBindViewHolder(RecyclerView.ViewHolder holder,int position)方法
這是綁定數(shù)據(jù)的
@Override
public void onBindMyViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof FruitViewHolder) {
FruitBean fruitBean = (FruitBean) mList.get(position);
((FruitViewHolder) holder).getBinding().setItem(fruitBean);
((FruitViewHolder) holder).getBinding().executePendingBindings(); //解決databinding閃爍問(wèn)題
} else if (holder instanceof TextViewHolder) {
TextBean textBean = (TextBean) mList.get(position);
((TextViewHolder) holder).getBinding().setItem(textBean);
((TextViewHolder) holder).getBinding().executePendingBindings(); //解決databinding閃爍問(wèn)題
}
}
這里是直接通過(guò)不同item布局對(duì)應(yīng)的Binding對(duì)象去設(shè)置對(duì)應(yīng)的數(shù)據(jù),注意:executePendingBindings()不要忘記了,他用于解決databinding閃爍問(wèn)題,感興趣的可以參考 RecyclerView使用databinding出現(xiàn)數(shù)據(jù)閃爍問(wèn)題
到這里已經(jīng)實(shí)現(xiàn)了RecyclerView中使用DataBinding,估計(jì)會(huì)有人會(huì)說(shuō)你這種寫(xiě)法不夠簡(jiǎn)潔,關(guān)于這一點(diǎn),我是這么想的,如果你需要在onBindViewHolder()里面做比較復(fù)雜的操作,比如獲取到某個(gè)item的View去做一些事情,你需要知道你用的到底是哪個(gè)ViewHolder,那么用這種方式還是可以的。如果只是單純的綁定數(shù)據(jù)和顯示數(shù)據(jù),其實(shí)還有一種簡(jiǎn)單的寫(xiě)法,可以參考這篇文章,親測(cè)還是比較不錯(cuò)的。
通過(guò)Data Binding為RecyclerView打造通用Adapter
歡迎學(xué)習(xí)交流這個(gè)系列的文章
DataBinding系列(一):DataBinding初認(rèn)識(shí)
DataBinding系列(二):DataBinding的基本用法
DataBinding系列(四):DataBinding進(jìn)階之路