本文是我的笔记以及Android的知识积累;
- 轻盈,整个类库只有 14 个类文件,aar 或 jar 包大小只有 13 KB
- 周到,支持 data type <–> item view binder 之间 一对一 和 一对多 的关系绑定
- 灵活,几乎所有的部件(类)都可被替换、可继承定制,面向接口 / 抽象编程
- 纯粹,只负责本分工作,专注多类型的列表视图 类型分发,绝不会去影响 views 的内容或行为
- 高效,没有性能损失,内存友好,最大限度发挥 RecyclerView 的复用性
- 可读,代码清晰干净、设计精巧,极力避免复杂化,可读性很好,为拓展和自行解决问题提供了基础
这是对MultiType的特性的释义,可能用起来没有什么问题,但是要知道为什么,如何实现?请继续看…
private Adapter extent RecyclerView.Adapter {
# 数据源
# 构造方法
# onCreatViewHolder(...){}
# onBindViewHodler(...){}
# getItemCount(){}
# getItemViewType(){}
}
实际写起来可能也没有什么大的问题,但是对于多ItemType的情况下,我们需要控制不同的type类型,在后续的需要、业务改动中,可能还需要调整,时间长了,即使是自己所写的代码也会感到无从下手,MultiType就应运而生。
其中比较新颖、有趣的想法:
- 所有的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 dataTypes = new ArrayList<>();
// 保存 数据源类型对应的 manager
private List 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();
}
}
/**
* 基本的 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();
}
}
/**
* 其子类处理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 findViewById(View itemView, @IdRes int viewId) {
return itemView.findViewById(viewId);
}
protected V findViewById(BaseViewHolder viewHolder, @IdRes int viewId) {
return findViewById(viewHolder.itemView, viewId);
}
}
测试用实体类.
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 {
@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 {
@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;
}
}
具体使用 Demo
// 伪造数据源
List