使用RecyclerView实现多type抽象需求

多Type需求

产品原型

1
最近在完成一个类型信息流产品,涉及到很多type类型

技术支撑

1
在技术层面上,通过RecyclerViewViewHolder,抽象业务逻辑,结合不同的type来注册不同的ViewHolder,然后各自ViewHolder处理对应样式的逻辑和业务

抽象业务

主要有两部分,一部分是支持多type本身的Adapter的抽象,一部分是由数据驱动列表的数据解析,同时包含后端的数据构建。

数据原型:

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
{
"data": {
"list": [
{
"cardType": "cardType_1",
"description": "",
"pic": "",
"title": "",
"id": "14499",
"count": "1"
},
{
"cardType": "cardType_2",
"video": "",
"videoUrl": "",
"musicList": [
],
"price": "",
"salePrice": "120"
},
{
"cardType": "cardType_3",
"advertising": "",
"advertisingTitle": "",
"advertisingUrl": [
],
"advertisingPrice": ""
}
]
}
}

典型的信息流中包含的cardtype样式会有很多种,每种都会相应的对应一种数据,然后把不同的数据生成一个json的列表,每个item是不同的对象和字段,这样我们很难使用json工具来反射这个list,所以需要自己去解析list元素所属卡片的数据格式。

Adapter抽象

正常的写法是,我们需要自己去继承Adapter,然后编写一个对应的ViewHolder,然后写逻辑,这样代码耦合度高,往往需要写很多代码,包括处理业务逻辑。

抽象思想:

1
2
一个列表中包含了不同的类型的卡片,每个卡片对应自己的数据对象,每个卡片都需要绑定自己的数据对象和逻辑,也就是说ViewHolder + Data.class 组成一个个体

上图中已经标注出相应的模式。

理想中的使用方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
GridLayoutManager layoutManager = new GridLayoutManager(getContext(), SPAN_COUNT);
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (items.size() > 0) {
Object object = items.get(position);
return (object instanceof MusicData ? SPAN_COUNT : 1;
}
return 1;
}
});

mRecyclerView.setLayoutManager(layoutManager);

adapter = new MultiAdapter();
adapter.register(MusicData.class, new MusicViewBinder());
adapter.register(VideoData.class, new VideoViewBinder());
adapter.register(MovVideoData.class, new MovViewBinder());
adapter.setItems(items);
mRecyclerView.setAdapter(adapter);

数据解析模块:

1