博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
<Android 基础(三十五)> RecyclerView多类型Item的正确实现姿势
阅读量:6540 次
发布时间:2019-06-24

本文共 7007 字,大约阅读时间需要 23 分钟。

简介

RecyclerView是我们开发过程中经常使用到的一个元素,原生的RecyclerView.Adapter基本上可以满足一般的需求,关于RecyclerView的基础介绍请移步:

关于多类型的Item,原生的Adapter可以通过getItemViewType返回对应的ViewHolder类型,然后在onCreateViewHolder传入的type参数,生成不同的ViewHolder,更要命的是数据绑定过程中onBindViewHolder只传入ViewHolder对象和position,针对不同的ViewHolder,我们只能通过instanceof和强制类型装换来对不同的ViewHolder进行不同的数据操作。

这样做的弊端就是,后续如果需要添加一个类型,几乎需要修改Adapter类中的每一个方法,不利于维护。

类结构

这里写图片描述

目的

  1. 便于维护。增删Item的类型不需要修改Adapter的代码;
  2. 条例清晰。不同类型的Item对应不同的Bean类,对应不用的ViewHolder,对应不同的layout
    item type <—-> layout <—> ViewHolder <—-> java bean
  3. 工厂接口。抽象出TypeFactory接口,针对同一个Bean,可以使用不同的layout和不同的ViewHolder。

思路

  1. 所有Bean类实现统一Visitable接口,实现type方法,返回对应的layout id;
  2. 创建BaseViewHolder使用泛型,T为Bean类。使用SparseArray存储View,View的id作为唯一标识。
  3. 具体的ViewHolder类,继承BaseViewHolder,传入不同的Bean类,方便不同的ViewHolder中绑定不同的数据。
  4. Adapter实现中使用Visitable List同一处理列表数据,使用事项TypeFactory接口的实例返回ItemType,viewHolder等

代码结构

这里写图片描述

代码内容

Visitable接口

public interface Visitable {    int type(TypeFactory typeFactory);}

TypeFactory接口

public interface TypeFactory {    int type(BannerBean bannerBean);    int type(ContentBean contentBean);    int type(SearchBean searchBean);    int type(DividerBean dividerBean);    BaseViewHolder createViewHolder(int type, View itemView);}

BaseViewHolder抽象类

public abstract  class BaseViewHolder
extends RecyclerView.ViewHolder{
SparseArray
mViews; View mItemView; public BaseViewHolder(View itemView) { super(itemView); mItemView = itemView; mViews = new SparseArray<>(); } public View getView(int resId) { View view = mViews.get(resId); if(view== null) { view = mItemView.findViewById(resId); mViews.put(resId, view); } return view; } public abstract void bindViewData(T data);}

TypeFactory实现类~ItemTypeFactory

public class ItemTypeFactory implements TypeFactory {
public static final int BANNER_ITEM_LAYOUT = R.layout.rv_item_banner; public static final int CONTENT_ITEM_LAYOUT = R.layout.rv_item_content; public static final int SEARCH_ITEM_LAYOUT = R.layout.rv_item_search; public static final int DIVIDER_ITEM_LAYOUT = R.layout.rv_item_divider; @Override public int type(BannerBean bannerBean) { return BANNER_ITEM_LAYOUT; } @Override public int type(ContentBean contentBean) { return CONTENT_ITEM_LAYOUT; } @Override public int type(DividerBean dividerBean){ return DIVIDER_ITEM_LAYOUT; } @Override public int type(SearchBean dividerBean){ return SEARCH_ITEM_LAYOUT; } @Override public BaseViewHolder createViewHolder(int type, View itemView) { switch (type) { case BANNER_ITEM_LAYOUT: return new BannerViewHolder(itemView); case SEARCH_ITEM_LAYOUT: return new SearchViewHolder(itemView); case CONTENT_ITEM_LAYOUT: return new ContentViewHolder(itemView); case DIVIDER_ITEM_LAYOUT: return new DividerViewHolder(itemView); default: return null; } }}

各种Java Bean类

BannerBean

public class BannerBean implements Visitable {
int[] mResIds; public BannerBean(int[] mResIds) { this.mResIds = mResIds; } public int[] getmResIds() { return mResIds; } public void setmResIds(int[] mResIds) { this.mResIds = mResIds; } @Override public int type(TypeFactory typeFactory) { return typeFactory.type(this); }}

ContentBean

public class ContentBean implements Visitable{
String content; public String getContent() { return content; } public void setContent(String content) { this.content = content; } public ContentBean(String content) { this.content = content; } @Override public int type(TypeFactory typeFactory) { return typeFactory.type(this); }}

DividerBean

public class DividerBean implements Visitable{
@Override public int type(TypeFactory typeFactory) { return typeFactory.type(this); }}

SearchBean

public class SearchBean implements Visitable {
@Override public int type(TypeFactory typeFactory) { return typeFactory.type(this); }}

MultiRecyclerAdapter

public class MultiRecyclerAdapter extends RecyclerView.Adapter
{ List
mData; TypeFactory typeFactory; public MultiRecyclerAdapter(List
mData) { this.mData = mData; this.typeFactory = new ItemTypeFactory(); } @Override public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false); return typeFactory.createViewHolder(viewType, view); } @Override public void onBindViewHolder(BaseViewHolder holder, int position) { holder.bindViewData(mData.get(position)); } @Override public int getItemViewType(int position) { return mData.get(position).type(typeFactory); } @Override public int getItemCount() { return (mData != null ? mData.size() : 0); }}

示例

public class MultiActivity extends AppCompatActivity {
@BindView(R.id.rv_content) RecyclerView rvContent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_weather); ButterKnife.bind(this); List
beans = new ArrayList<>(); int[] resIds = {R.mipmap.banner_one, R.mipmap.banner_two, R.mipmap.banner_three, R.mipmap.banner_four, R.mipmap.banner_five}; beans.add(new BannerBean(resIds)); beans.add(new SearchBean()); beans.add(new DividerBean()); beans.add(new ContentBean("one")); beans.add(new ContentBean("one")); beans.add(new ContentBean("one")); beans.add(new DividerBean()); beans.add(new ContentBean("two")); beans.add(new ContentBean("two")); beans.add(new ContentBean("two")); beans.add(new DividerBean()); beans.add(new ContentBean("three")); beans.add(new ContentBean("three")); beans.add(new ContentBean("three")); beans.add(new DividerBean()); beans.add(new ContentBean("four")); beans.add(new ContentBean("four")); beans.add(new ContentBean("four")); beans.add(new DividerBean()); MultiRecyclerAdapter multiRecyclerAdapter = new MultiRecyclerAdapter(beans); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); rvContent.setAdapter(multiRecyclerAdapter); rvContent.setLayoutManager(linearLayoutManager); }}

简单效果

这里写图片描述

写在最后

思路来源:

github上也有很多开源的万能Adapter,但是个人感觉这个思路虽然实现上代码会相对较多,但是层次分析,便于维护,扩展性较好。想要添加一个新类型的ItemType,只需要稍作修改即可快速完成,不用修改Adapter的代码。

转载于:https://www.cnblogs.com/lanzhi/p/6467145.html

你可能感兴趣的文章
Windows 7删除用户配置文件后使用临时配置文件
查看>>
Centos下安装memcached+memcached教程
查看>>
聊聊Java中的异常机制
查看>>
在linux系统下把多个终端合并在一个窗口
查看>>
我的友情链接
查看>>
MongoDB安装的坑
查看>>
pytorch解决鸢尾花分类
查看>>
centos6.2 kvm安装详解
查看>>
centos安装scrapy
查看>>
给图片局部区域加链接
查看>>
CCNA 学习笔记(十)--广域网(PPP)
查看>>
Outlook 打印时候,无法打全
查看>>
那些年,你所经历的运维
查看>>
oracle数据库使用游标实现大写数字转换成小写数字
查看>>
Shell脚本与计划任务
查看>>
中缀表达式转后缀表达式 并计算后缀表达式
查看>>
20、云安全之修改SSH端口 / 禁止ROOT登陆
查看>>
深入浅出DIV+CSS
查看>>
JavaScript系列:ECMAScript语句
查看>>
HR的工资条小密码---添加分页符
查看>>