学习MultiViewAdapter——1
来源:互联网 发布:php魔术方法isset() 编辑:程序博客网 时间:2024/05/29 19:27
本文讲到的关于MultiViewAdapter,是学习国外牛人在GitHub上的开源项目。具体的使用方法可以看Wiki。
项目中我们会经常用到RecyclerView实现多种效果,这里简单提一下那几个方法。
getItemViewType()
返回item的视图类型,默认返回的是0.与ListView适配器不同,视图类型不需要连续不断。可以考虑使用id来识别项视图类型。onCreateViewHolder()
根据不同类型的item来创建不同类型的viewholderonBindViewHolder()
根据不同类型的viewholder来绑定不同的数据
还有一些方法这里就不提了,基本上的模板代码就是那样。
例如:
public class CustomAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private static final String TAG = "CustomAdapter"; private Context context; private LayoutInflater inflater; private List<JavaBean> items = new ArrayList<>(); public CustomAdapter(Context context){ this.context = context; inflater = LayoutInflater.from(context); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == JavaBean.TYPE_A) { View view = inflater.inflate(R.layout.item_chat_right, parent, false); AHolder aHolder = new AHolder(view); return aHolder; }else if (viewType == JavaBean.TYPE_B){ View v = inflater.inflate(R.layout.item_chat_left,parent,false); BHolder bHolder = new BHolder(v); return bHolder; } return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof AHolder) { AHolder aHolder = (AHolder) holder; if (items != null) { aHolder.tvChatContent.setText(items.get(position).getText()); aHolder.imgChatHead.setImageURI(Uri.parse(items.get(position).getHeadUrl())); } }else if (holder instanceof BHolder){ BHolder bHolder = (BHolder) holder; if (items!=null){ bHolder.tvChatContent.setText(items.get(position).getText()); } } } @Override public int getItemCount() { if (items!=null) return items.size(); else return 0; } @Override public int getItemViewType(int position) { return items.get(position).getType(); } public void addMsg(ChatBean msg){ items.add(msg); notifyItemInserted(items.size()); } public class AHolder extends RecyclerView.ViewHolder { private TextView tvChatContent; private SimpleDraweeView imgChatHead; public AHolder(View itemView) { super(itemView); tvChatContent = (TextView) itemView.findViewById(R.id.tv_chat_right); imgChatHead = (SimpleDraweeView) itemView.findViewById(R.id.img_chat_head_right); } } public class BHolder extends RecyclerView.ViewHolder { private TextView tvChatContent; private SimpleDraweeView imgChatHead; public BHolder(View itemView) { super(itemView); tvChatContent = (TextView) itemView.findViewById(R.id.tv_chat_left); imgChatHead = (SimpleDraweeView) itemView.findViewById(R.id.img_chat_head_left); } }}
看到了吧,如果使用常规的方式去写也是没有问题。像我之前实现了汽车上使用的WiFi列表,我都没有用RecyclerView直接一个ListView就搞定了,但是如果要有9-8种ViewType呢?你还敢这么写吗。所以说我们要么自己去封装库,要么上网用别人写好的。这里面有两个问题,第一种是自己写不来可扩展性强的库,没有那水平。第二种是用第三方的库,有了问题的话,如果不熟悉源码,那么有一个低概率的bug,只要是关于这个库的,基本上就没有办法解决。所以我们平时闲着的时候,要去多看看第三方库里面的源代码。这样以后有了问题,心就不虚了。
该库的作者在自己的博客中给出了一张图:
1.DataManger — 它持有数据而在数据修改的时候调用动画并且提供了DiffUtil的支持。有两种DataManager:显示list的DataListManager以及显示一个item(比如Header, Footer 等)的DataItemManager。
2.RecyclerAdapter继承了CoreRecyclerAdapter(处理数据),子类的适配器可以继承RecyclerAdapter,因为RecyclerAdapter可以持有多个 ItemBinder和DataManager来处理View与数据。
3.ItemBinder —ItemBinder的职责是创建和绑定viewholder。它提供了关于View的基础操作,例如:点击,长按,选择item的监听事件,它还有一个type参数,接收需要显示的model类。ItemBinder需要在子类实现RecyclerAdapter的类中注册。
我们先说一说ItemViewHolder
RecyclerView必须有一个ViewHolder,所以先对ViewHolder做了封装。
public class ItemViewHolder<M> extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { private M item; private OnItemClickListener<M> itemClickListener; private OnItemLongClickListener<M> itemLongClickListener; private ItemActionListener actionListener; public ItemViewHolder(View itemView) { super(itemView); itemView.setOnClickListener(this); itemView.setOnLongClickListener(this); } @RestrictTo(RestrictTo.Scope.LIBRARY) @Override public final void onClick(View view) { if (null == itemClickListener) return; itemClickListener.onItemClick(view, getItem()); } @RestrictTo(RestrictTo.Scope.LIBRARY) @Override public final boolean onLongClick(View view) { return null != itemLongClickListener && itemLongClickListener.onItemLongClick(view, getItem()); } final void setItemActionListener(ItemActionListener actionListener) { this.actionListener = actionListener; } public final M getItem() { return item; } //////////////////////////////////////// ///////// Public Methods /////////////// //////////////////////////////////////// final void setItem(M item) { this.item = item; } /** * item选择 */ protected final void toggleItemSelection() { actionListener.onItemSelectionToggled(getAdapterPosition()); } /** * item展开 */ protected final void toggleItemExpansion() { actionListener.onItemExpansionToggled(getAdapterPosition()); } /** * 子视图可以调用 {@link DataGroupManager}'s来扩展 * */ protected final void toggleGroupExpansion() { actionListener.onGroupExpansionToggled(getAdapterPosition()); } protected final void setItemClickListener(OnItemClickListener<M> itemClickListener) { this.itemClickListener = itemClickListener; } protected final void setItemLongClickListener(OnItemLongClickListener<M> itemLongClickListener) { this.itemLongClickListener = itemLongClickListener; } public final boolean isItemSelected() { return actionListener.isItemSelected(getAdapterPosition()); } public final boolean isItemExpanded() { return actionListener.isItemExpanded(getAdapterPosition()); } public final boolean isInActionMode() { return actionListener.isAdapterInActionMode(); } /** * 返回ItemViewHolder的滑动方向。 * 默认返回0 * 这个方法可以被子类覆盖,可以提供有效的滑动方向标志。 * * @return A binary OR of direction flags. */ public int getSwipeDirections() { return 0; } /** * 返回ItemViewHolder的拖,拽动方向。 * 默认返回0 * 这个方法可以被子类覆盖,可以提供有效的滑动方向标志。 * * @return A binary OR of direction flags. */ public int getDragDirections() { return 0; } /** * 该方法允许用户开始拖拽viewholder */ public final void startDrag() { actionListener.onStartDrag(this); } public interface OnItemClickListener<M> { void onItemClick(View view, M item); } public interface OnItemLongClickListener<M> { boolean onItemLongClick(View view, M item); }}
在ViewHolder中,定义了各种点击事件的监听,这样子类在实现点击事件的时候,在ViewHolder中实现就可以了。其中ItemActionListener
定义了各种事件的监听。
接着我们看看上面提到的关于ItemBinder
public abstract class ItemBinder<M, VH extends ItemViewHolder<M>> { private List<ItemDecorator> itemDecorators; public ItemBinder() { } public ItemBinder(ItemDecorator itemDecorator) { addDecorator(itemDecorator); } public abstract VH create(LayoutInflater inflater, ViewGroup parent); /** * @param holder itemholder * 给列表设置数据 * @param item 持有数据的对象 * @see #bind(ItemViewHolder, Object, List) */ public abstract void bind(VH holder, M item); /** * @param item 持有数据的对象 */ public abstract boolean canBindData(Object item); public void bind(VH holder, M item, List payloads) { bind(holder, item); } public int getSpanSize(int maxSpanCount) { return 1; } /** * 添加分割线 */ public final void addDecorator(ItemDecorator itemDecorator) { addDecorator(itemDecorator, -1); } public final void addDecorator(ItemDecorator itemDecorator, int priority) { if (null == itemDecorators) { itemDecorators = new ArrayList<>(); } if (priority >= 0 && itemDecorators.size() > priority) { itemDecorators.add(priority, itemDecorator); } else { itemDecorators.add(itemDecorator); } } /////////////////////////////////////////// /////////// Internal API ahead. /////////// /////////////////////////////////////////// void bindViewHolder(VH holder, M item) { bind(holder, item); } void bindViewHolder(VH holder, M item, List payloads) { bind(holder, item, payloads); } VH createViewHolder(LayoutInflater inflater, ViewGroup parent, ItemActionListener actionListener) { VH viewHolder = create(inflater, parent); viewHolder.setItemActionListener(actionListener); return viewHolder; } boolean isItemDecorationEnabled() { return itemDecorators != null; } void getItemOffsets(Rect outRect, int position, @PositionType int positionType) { if (null == itemDecorators) { return; } for (ItemDecorator itemDecorator : itemDecorators) { itemDecorator.getItemOffsets(outRect, position, positionType); } } void onDraw(Canvas canvas, RecyclerView parent, View child, int position, @PositionType int positionType) { if (null == itemDecorators) { return; } for (ItemDecorator itemDecorator : itemDecorators) { itemDecorator.onDraw(canvas, parent, child, position, positionType); } }}
- 子类可以继承ItemBinder,并且将Mode数据放入泛型中
create(...)
方法用来返回布局bind
方法用来设置数据canBindData()
这个方法很重要,我们需要确认item数据是否是Mode类的一个实例,这个方法我会在后面讲,他有什么用。getSpanSize()
有了这个也就是为你提供了更方便的跨列合并的方法addDecorator
可以为你的ItemBinder添加分割线到了这里,已经将View布局已经分离出来了,正如作者说到的“ItemBinder的职责是创建和绑定视图” 。那么我将在下一篇介绍剩下的两个重要概念
RecyclerAdapter
与DataManger
在工作中,如果打杂的任务做的太多了,时间太长了,那么你就真的是这家公司打杂的人了。后知后觉,每到升职加薪的时候,领导在问你工作专业性的时候,你就无话可说了。
- 学习MultiViewAdapter——1
- 学习MultiViewAdapter——2
- 学习MultiViewAdapter——3
- 学习MultiViewAdapter——4
- C++学习1——入门学习
- jQuery 学习—1
- 命令学习—1
- Qt学习—1
- shell 学习 — 1
- 【学习】——高效学习
- 机器学习—学习笔记
- OpenGL学习——1
- STM32CUBE学习——1
- Struts2学习——1
- Jmeter学习——1
- Web开发学习笔记1——PHP学习笔记
- Unix_Linux学习(1)——vim编辑器的使用学习
- Clojure 学习入门(1)—— 学习资料
- 2017.11.12笔记
- 火车票购票系统模式
- TCP之实现简单聊天室
- 让人个人
- iOS SDWebimage~SDImageCache计算缓存大小
- 学习MultiViewAdapter——1
- AJax提交表单数据到后台springmvc接收
- electron 将pc端(vue)页面打包为桌面端应用
- 简单的mvp+retrofit+rxjava示例
- C语言删除链表中的结点
- 腾讯企业邮箱阿里云端口25发送失败
- 使用多文件编译线性表时出现,LNK2005:int_cdecl int_list(..) 解决办法
- unity3d脚本rederTexture 旋转
- HTTP消息头