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
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2018-10-18 22:25  天涯海角路  阅读(304)  评论(0)    收藏  举报