MultiType多列表框架思想
前言
MultiType 的特性
常用写法
核心思想
源码
用法
前言
本文是我的笔记以及Android的知识积累;
MultiType 的特性
轻盈,整个类库只有 14 个类文件,aar 或 jar 包大小只有 13 KB
周到,支持 data type <–> item view binder 之间 一对一 和 一对多 的关系绑定
灵活,几乎所有的部件(类)都可被替换、可继承定制,面向接口 / 抽象编程
纯粹,只负责本分工作,专注多类型的列表视图 类型分发,绝不会去影响 views 的内容或行为
高效,没有性能损失,内存友好,最大限度发挥 RecyclerView 的复用性
可读,代码清晰干净、设计精巧,极力避免复杂化,可读性很好,为拓展和自行解决问题提供了基础
这是对MultiType的特性的释义,可能用起来没有什么问题,但是要知道为什么,如何实现?请继续看…
常用写法
private Adapter extent RecyclerView.Adapter {
# 数据源
# 构造方法
# onCreatViewHolder(...){}
# onBindViewHodler(...){}
# getItemCount(){}
# getItemViewType(){}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
实际写起来可能也没有什么大的问题,但是对于多ItemType的情况下,我们需要控制不同的type类型,在后续的需要、业务改动中,可能还需要调整,时间长了,即使是自己所写的代码也会感到无从下手,MultiType就应运而生。
核心思想
扩展 RecyclerView.Adapter 类, 
当前所有的数据存储 
List data 保存所有的数据源
List itemDataClassName 保存所以数据源类型的 className (能够唯一标识的,存取规则保持一致即可)
List 保存所有对应与 itemData 管理类
将视图、数据绑定操作放到 Manager 的具体实现类中去处理
使用 List itemDataClassName 的下标指代 ItemType
扩展 RecyclerView.ViewHolder 类,可做一些功能的拓展
ViewHolderManager 其主要职责:返回视图、处理数据与视图的绑定
其中比较新颖、有趣的想法: 
- 所有的ItemType有数据类型集合中的下标所自行控制,这就让我们不用再关心不同position对应的itemType是多少的问题; 
- register 操作,对列表所加载数据类型注册进 adapter
源码
结合上面的思想,精简出了3个java类,就可以基本实现:
/**
 * Adapter的主要实现。
 *
 * @author egan on 2018/4/20.
 * @date 2018/4/20 上午10:26.
 */
public class BaseAdapter extends RecyclerView.Adapter<BaseViewHolder> {
    // 数据源
    private List data = new ArrayList<>();
    // 保存 数据源类型
    private List<String> dataTypes = new ArrayList<>();
    // 保存 数据源类型对应的 manager
    private List<ViewHolderManager> dataManagers = new ArrayList<>();
    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // 根据 viewType 获取 获取预订类型,>> manage >>> 获得ViewHolder
        // itemViewType 的值即对应 数据类型的下标
        return dataManagers.get(viewType).onCreateViewHolder(parent);
    }
    @Override
    public int getItemViewType(int position) {
        // return super.getItemViewType(position);
        Object o = data.get(position);
        // 根据数据对象去预订的类型中去获取对应
        return dataTypes.indexOf(o.getClass().getName());
    }
    @Override
    public void onBindViewHolder(BaseViewHolder holder, int position) {
        // itemViewType 的值即对应 数据类型的下标
        int index = getItemViewType(position);
        // 获取 Item 的数据
        Object itemData = data.get(position);
        // 获取 Item 数据类型对应的 manager
        ViewHolderManager itemViewHolderManager = dataManagers.get(index);
        itemViewHolderManager.onBindViewHolder(itemData, holder);
    }
    @Override
    public int getItemCount() {
        return this.data == null ? 0 : this.data.size();
    }
    // 将类型注册进入 adapter 中,表明该 adapter包含哪些类型
    public void register(Class o, ViewHolderManager manager) {
        if (dataTypes.contains(o.getName())) {
            dataManagers.set(dataTypes.indexOf(o.getName()), manager);
        } else {
            dataTypes.add(o.getName());
            dataManagers.add(manager);
        }
    }
    public void setData(List data) {
        this.data = data;
        notifyDataSetChanged();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
 * 基本的 ViewHolder,用于自己的处理
 *
 * @author egan on 2018/4/20.
 * @date 2018/4/20 上午10:02.
 */
public class BaseViewHolder extends RecyclerView.ViewHolder {
    public BaseViewHolder(View itemView) {
        super(itemView);
    }
    public int getItemPosition() {
        return this.getAdapterPosition();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * 其子类处理View视图的返回以及视图与数据的绑定.
 *
 * @author egan on 2018/4/20.
 * @date 2018/4/20 上午10:10.
 */
public abstract class ViewHolderManager<T> {
    public BaseViewHolder onCreateViewHolder(ViewGroup parent) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(getItemLayoutId(), parent, false);
        return new BaseViewHolder(itemView);
    }
public abstract void onBindViewHolder(T t, BaseViewHolder viewHolder);
    @LayoutRes
    public abstract int getItemLayoutId();
    private <V extends View> V findViewById(View itemView, @IdRes int viewId) {
        return itemView.findViewById(viewId);
    }
    protected <V extends View> V findViewById(BaseViewHolder viewHolder, @IdRes int viewId) {
        return findViewById(viewHolder.itemView, viewId);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
用法
测试用实体类.
class Test1 {
    public Test1(String name) {
        this.name = name;
    }
    String name;
}
class Test2 {
    public Test2(int age) {
        this.age = age;
    }
    int age;
}
class Test1Manager extends ViewHolderManager<Test1> {
    @Override
    public void onBindViewHolder(Test1 test1, BaseViewHolder viewHolder) {
        TextView text1 = findViewById(viewHolder, android.R.id.text1);
        TextView text2 = findViewById(viewHolder, android.R.id.text2);
        text1.setText("这是 Test 1");
        text2.setText("姓名 >>> " + test1.name);
    }
    @Override
    public int getItemLayoutId() {
        return android.R.layout.simple_list_item_2;
    }
}
class Test2Manager extends ViewHolderManager<Test2> {
    @Override
    public void onBindViewHolder(Test2 test1, BaseViewHolder viewHolder) {
        TextView text1 = findViewById(viewHolder, android.R.id.text1);
        TextView text2 = findViewById(viewHolder, android.R.id.text2);
        text1.setText("这是 Test 2");
        text2.setText("年龄 >>> " + test1.age);
    }
    @Override
    public int getItemLayoutId() {
        return android.R.layout.simple_list_item_2;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
具体使用 Demo
// 伪造数据源
List<Object> allData = new ArrayList<>();
allData.add(new Test1("maka 1"));
allData.add(new Test1("maka 2"));
allData.add(new Test2(1));
allData.add(new Test2(2));
// 创建 Adapter 实例,并注册 Model 与 Manager 
BaseAdapter baseAdapter = new BaseAdapter();
baseAdapter.register(Test1.class, new Test1Manager());
baseAdapter.register(Test2.class, new Test2Manager());
// 绑定 RecyclerView 与 Adapter
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(baseAdapter);
// 刷新数据源
baseAdapter.setData(allData);
--------------------- 
作者:Egan 
来源:CSDN 
原文:https://blog.csdn.net/qq_16251833/article/details/80060959 
版权声明:本文为博主原创文章,转载请附上博文链接!
                    
                
                
            
        
浙公网安备 33010602011771号