使用 RecyclerView 实现下面的效果:
- 有两种布局,红色布局和蓝色布局
- 偶数位置的是红色布局,奇数位置的是蓝色布局
按照一般的方法来实现 Adapter 的话,代码如下
1 | import android.support.v7.widget.RecyclerView; |
因为有多种布局,所以重点关注的是如何判断在某一个位置要如何展示哪一个布局,RecyclerView.Adapter 提供了 int getItemViewType(int position)
方法让我们重写,给每一个布局指定一个唯一标识 ItemViewType
按照效果图:偶数位置的是红色布局,奇数位置的是蓝色布局,所以方法重写如下
1 | // 布局的唯一标识 |
有了布局的唯一标识 ItemViewType
之后,就可以在RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
和void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
中根据这个唯一标识,创建和绑定不同的 ViewHolder 了。
缺陷
这个写法没什么毛病,但是在维护上会有一些问题。如果将来要增加一个新的布局,假设位置的尾数逢 5 的地方需要显示绿色布局,就需要改动几个地方
- 增加或布局的唯一标识,也就是改动这个地方
1 | private static final int TYPE_RED = 0; |
- 增加一个 ViewHolder
1 | private static class GreenViewHolder extends RecyclerView.ViewHolder { |
- 修改
int getItemViewType(int position)
的 if-else 判断
1 |
|
- 修改
RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
方法,增加一个 ViewHolder
1 |
|
- 修改
void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
方法,处理 GreenViewHolder 的逻辑
1 |
|
发现问题
可以看到增加一个布局,需要改动很多地方。问题的根源就在于 if-else 判断这一块代码。如果让一个类来帮我们在 int getItemViewType(int position)
方法中返回唯一标识,同时在 RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
和void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
方法中帮我们根据 itemViewType 拿到 ViewHolder,这样就能大幅度地减少代码。
实现
可以看到 itemViewType 和 ViewHolder 是一一对应的关系,那么就可以使用 HashMap<Integer, RecyclerView.ViewHolder>
来存放 itemViewType 和 ViewHolder。
接着再定义一个接口
1 | public interface AdapterDelegate<T> { |
把确定唯一标识、创建 ViewHolder 和 绑定 ViewHolder 的工作交给实现接口的具体的 ViewHolder 来实现。
最终效果
MyAdapter 现在只有这些代码
1 | public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { |
剩下的就是定义 ViewHolder 实现 AdapterDelegate
1 | /** |
核心代码的实现
这个类是按照 JOE’S GREAT ADAPTER HELL ESCAPE 介绍的思想来实现的,核心指出就在于 itemViewType 和 ViewHolder 是一一对应的关系。
AdapterDelegate 接口
1 | import android.support.v7.widget.RecyclerView; |
AdapterDelegatesManager 的实现
1 | import android.support.v7.widget.RecyclerView; |
参考来源
http://hannesdorfmann.com/android/adapter-delegates
https://github.com/sockeqwe/AdapterDelegates