RecyclerView
是一个你们经常使用的列表控件,在列表中难免会出现多种类型的布局,这时adapter
中多种类型的判断就会充满着switch
的坏味道,可怕的是需求变动,增长或修改新的类型时,全部的改动都在adapter
中进行,没有一个良好的扩展性。MutliItem
主要就是解决这些问题,在正常使用中作到了Adapter
零编码,解放了复杂的Adapter
类,本库提供了多类型和ViewHolder
建立绑定的管理器,这样Adapter
经过依赖倒置与列表中的多类型解耦,还提升了扩展性。在本库中不一样实体类能够直接当成数据源绑定到adapter
中,你不用去担忧item type
的计算,而且对每种类型的ViewHolder
也作到了隔离。
本库的定位并非大而全,可是会尽可能作到简单易用。java
Github地址:MultiItem,请你们多多关注,更多更新会首先在GitHub上体现,也会在第一时间在本平台发布android
在Project root
的build.gradle
中添加:git
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}复制代码
在Module
中添加(最新版本请在源码地址查看):github
dependencies {
compile 'com.github.free46000:MultiItem:0.9.7'
}复制代码
这里因为单一和多种类型写法上没有差异,因此就不单独贴出单一类型的列表代码了。
注册多种类型ViewHolderManager
,并为adapter
设置多种类型数据源:数组
//初始化adapter
BaseItemAdapter adapter = new BaseItemAdapter();
//为TextBean数据源注册ViewHolderManager管理类
adapter.register(TextBean.class, new TextViewManager());
//为更多数据源注册ViewHolderManager管理类
adapter.register(ImageTextBean.class, new ImageAndTextManager());
adapter.register(ImageBean.class, new ImageViewManager());
//组装数据源list
List<Object> list = new ArrayList<>();
list.add(new TextBean("AAA"));
list.add(new ImageBean(R.drawable.img1));
list.add(new ImageTextBean(R.drawable.img2, "BBB" + i));
//为adapter注册数据源list
adapter.setDataItems(list);
recyclerView.setAdapter(adapter);复制代码
ViewHolder
管理类的子类TextViewManager
类,其余类类似,下面贴出本类所有代码,是否是很是清晰:bash
public class ImageViewManager extends BaseViewHolderManager<ImageBean> {
@Override
public void onBindViewHolder(BaseViewHolder holder, ImageBean data) {
//在指定viewHolder中获取控件为id的view
ImageView imageView = getView(holder, R.id.image);
imageView.setImageResource(data.getImg());
}
@Override
protected int getItemLayoutId() {
//返回item布局文件id
return R.layout.item_image;
}
}复制代码
至此本库的多种类型列表用法已经完成,并无修改或继承RecyclerView Adapter
类,彻底使用默认实现BaseItemAdapter
便可。maven
这是一种特殊的需求,须要在运行时经过数据源中的某个属性,判断加载的布局,典型的就是聊天功能,相同消息数据对应左右两种气泡视图,在此处贴出注册时的关键代码,其余和多种类型列表相似:ide
//初始化adapter
BaseItemAdapter adapter = new BaseItemAdapter();
//为XXBean数据源注册XXManager管理类组合
adapter.register(MessageBean.class, new ViewHolderManagerGroup<MessageBean>(new SendMessageManager(), new ReceiveMessageManager()) {
@Override
public int getViewHolderManagerIndex(MessageBean itemData) {
//根据message判断是否本人发送并返回对应ViewHolderManager的index值
return itemData.getSender().equals(uid) ? 0 : 1;
}
});
recyclerView.setAdapter(adapter);复制代码
点击监听:布局
adapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(BaseViewHolder viewHolder) {
//经过viewHolder获取须要的数据
toastUser(String.format("你点击了第%s位置的数据:%s", viewHolder.getItemPosition()
, viewHolder.getItemData()));
}
});复制代码
长按监听:gradle
adapter.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public void onItemLongClick(BaseViewHolder viewHolder) {
//经过viewHolder获取须要的数据
toastUser(String.format("你长按了第%s位置的数据:%s", viewHolder.getItemPosition()
, viewHolder.getItemData()));
}
});复制代码
ViewHolderManager
提供视图建立绑定等工做ItemTypeManager
找到对应的ViewHolderManager
ViewHolder管理源码类为ViewHolderManager
,使用者会首先注册数据源和本实例的对应关系,由类型管理类提供统一管理。
adapter
调用本类方法的时候传入并作出通用处理ViewHolder
的建立与绑定方法,为了方便后续使用,写了一个简单的BaseViewHolderManager
实现类,请读者根据业务自行决定是否须要使用更灵活的基类,这里贴出须要复写的两个方法,延续了Adapter
中的命名规则,在使用中减小一些认知成本: /** * 建立ViewHolder * {@link android.support.v7.widget.RecyclerView.Adapter#onCreateViewHolder} */
@NonNull
public abstract V onCreateViewHolder(@NonNull ViewGroup parent);
/** * 为ViewHolder绑定数据 * {@link android.support.v7.widget.RecyclerView.Adapter#onBindViewHolder} * * @param t 数据源 */
public abstract void onBindViewHolder(@NonNull V holder, @NonNull T t);复制代码
组合管理源码类为ViewHolderManagerGroup
,本实例须要一个ViewHolderManager
集合,并增长经过数据源指定哪一个ViewHolderManager
的方法,使用者一样会注册数据源和本实例的对应关系,由类型管理类对本类中的ViewHolderManager
集合进行统一注册管理。下面贴出关键代码:
private ViewHolderManager[] viewHolderManagers;
/** * @param viewHolderManagers 相同数据源对应的全部ViewHolderManager */
public ViewHolderManagerGroup(ViewHolderManager... viewHolderManagers) {
if (viewHolderManagers == null || viewHolderManagers.length == 0) {
throw new IllegalArgumentException("viewHolderManagers can not be null");
}
this.viewHolderManagers = viewHolderManagers;
}
/** * 根据item数据源中的属性判断应该返回的对应viewHolderManagers的index值 * * @param itemData item数据源 * @return index值应该是在viewHolderManagers数组有效范围内 */
public abstract int getViewHolderManagerIndex(T itemData);复制代码
类型管理源码类为ItemTypeManager
,经过数据源className List
和viewHolderManager List
两组集合对类型进行管理,并对Adapter
提供注册和对应关系查找等方法的支持,这里并无把这个地方设计灵活,若是有一些变化仍是但愿能够在ViewHolderManager
作出适配。
viewHolderManager
时比较简单,关键代码:/** * 经过数据源`className List`和`viewHolderManager List`两组集合对类型进行管理 * * @param cls 数据源class * @param manager ViewHolderManager * @see com.freelib.multiitem.adapter.BaseItemAdapter#register(Class, ViewHolderManager) */
public void register(Class<?> cls, ViewHolderManager manager) {
register(getClassName(cls), manager);
}复制代码
viewHolderManager
时,关键代码:/** * 经过group获取一组ViewHolderManager循环注册,并生成不一样的className做为标识<br> * 其余相似{@link #register(Class, ViewHolderManager)} * * @param cls 数据源class * @param group 多个ViewHolderManager的组合 * @see com.freelib.multiitem.adapter.BaseItemAdapter#register(Class, ViewHolderManagerGroup) */
public void register(Class<?> cls, ViewHolderManagerGroup group) {
ViewHolderManager[] managers = group.getViewHolderManagers();
for (int i = 0, length = managers.length; i < length; i++) {
register(getClassNameFromGroup(cls, group, managers[i]), managers[i]);
}
itemClassNameGroupMap.put(getClassName(cls), group);
}复制代码
但愿你们会喜欢,多多留言交流