RecyclerView Adapter

  1. 为RecyclerView提供更简单的适配器实现方式,不断更新完好中。

  2. Demo视频演示

  3. GitHub地址

  4. 博客

使用

  • 类库还在开发中。临时没有公布到Jcenter,所以须要在yourProject.gradle文件里加入例如以下代码进行依赖
    allprojects {
repositories {
maven { url 'https://dl.bintray.com/chendongmarch/maven' }
}
}
  • yourApp.gradle文件里加入依赖
    compile 'com.march.lib-adapter:lib-adapter:1.0.0'

BaseViewHolder 的使用

  • 通用ViewHolder,内部使用SparseArray实现View的缓存。
//BaseViewHolder

//获取控件
public <T extends View> T getView(int resId)
public <T extends View> T getView(String resId)
//设置可见
public RvViewHolder setVisibility(int resId, int v)
//文字
public RvViewHolder setText(int resId, String txt)
//图片
public RvViewHolder setImg(int resId, int imgResId)
//监听
public RvViewHolder setClickLis(int resId, View.OnClickListener listener)

通用适配器

单类型数据适配

  • SimpleRvAdapter
//一个简单的实现,实体类不须要再去实现RvQuickInterface接口
SimpleRvAdapter simpleAdapter =
new SimpleRvAdapter<Demo>(self, demos, R.layout.rvquick_item_a) {
@Override
public void onBindView(RvViewHolder holder, Demo data, int pos) {
holder.setText(R.id.item_a_tv, data.title);
}
};

多类型数据适配

  • TypeRvAdapter

    1. 多类型数据适配时须要接受ITypeAdapterModel(接口)类型的的数据,因此进行多类型数据适配时,你的Model须要实现ITypeAdapterModel告知Adapter数据的type

    2. addType(int type,int res)方法用来给每种类型的数据加入不同的布局文件,达到多类型适配的目的。

// Demo类必须实现 ITypeAdapterModel 接口
TypeRvAdapter<Demo> typeAdapter =
new TypeRvAdapter<Demo>(context, data) {
@Override
public void onBindView(RvViewHolder holder, Demo data, int pos, int type) {
//依据类型绑定数据
switch (type) {
case Demo.CODE_DETAIL:
holder.setText(R.id.item_quickadapter_type_title, data.getmDemoTitle()).setText(R.id.item_quickadapter_desc, data.getmDescStr());
break;
case Demo.JUST_TEST:
holder.setText(R.id.item_quickadapter_title, data.getmDemoTitle());
break;
}
} };
typeAdapter.addType(Demo.CODE_DETAIL, R.layout.item_layout_a)
.addType(Demo.JUST_TEST, R.layout.item_layout_b);

九宫格模式适配

  • SectionRvAdapter

    1. 每一个Header以下由多个item。相似微信九宫格照片展示,SectionRvAdapter实际上是多类型适配(TypeRvAdapter)的一种特殊形式,内置了SectionHeader类型的数据,用来更简单的实现九宫格模式的数据适配,由于多类型数据适配的特点他都能够使用,也就是说你能够定义多种类型的数据展示。

    2. 作为ItemHeader的数据类型须要继承AbsSectionHeader(抽象类)

class ItemHeader extends AbsSectionHeader {
String itemHeaderTitle;
}
  1. 作为每一个Section内容的数据类型,假设他是单类型的不须要做其它操作。假设有多种类型的内容须要实现ITypeAdapterModel,具体參照多类型数据适配多类型数据适配
class Content {
int contentIndex
String contentTitle;
}

使用 ISectionRule 配置数据

  1. ISectionRule接口,进行九宫格模式适配使用 ISectionRule 配置数据时,须要加入ISectionRule,这是一种规则。adapter会依据你提供的规则自己主动生成Header

  2. 提供了两种构造方法

// 直接配置 item header 和 content 的 layout 资源
public SectionRvAdapter(Context context,List<ID> originDatas,
int headerLayoutId, int contentLayoutId)
// 仅仅加入 header 的 layout 资源。content的资源能够使用addType方法加入
public SectionRvAdapter(Context context, List<ID> originDatas,
int headerLayoutId)
// ItemHeader表示header的数据类型,Content表示内部数据的数据类型
// 初始化,加入header 和 content的布局文件
adapter = new SectionRvAdapter<ItemHeader, Content>(
this,
contents,
R.layout.item_header_header,
R.layout.item_header_content) {
@Override
protected void onBindItemHeader(BaseViewHolder holder, ItemHeader data, int pos, int type) {
holder.setText(R.id.info1, data.getItemHeaderTitle());
} @Override
protected void onBindContent(BaseViewHolder holder, Content data, int pos, int type) {
holder.setText(R.id.tv, String.valueOf(data.contentIndex));
}
}; // 加入ISectionRule
adapter.addItemHeaderRule(new ISectionRule<ItemHeader, Content>() {
@Override
public ItemHeader buildItemHeader(int currentPos, Content preData, Content currentData, Content nextData) {
// 生成header数据
return new ItemHeader("create new header " + currentData.contentIndex);
} @Override
public boolean isNeedItemHeader(int currentPos, Content preData, Content currentData, Content nextData) {
// 什么时候创建header(当是第一个数据或者index是7的倍数时,插入一个header)
return currentPos == 0 || currentData.contentIndex % 7 == 1;
}
});
mRv.setAdapter(adapter);

使用 HashMap 配置数据

  1. 一个 ItemHeader 下有多个 Content。相似Map<ItemHeader,Content>的数据结构,能够选择在外面构造好数据来进行数据适配

  2. HashMap是无序的,为了保证数据的有序性,使用LinkedHashMap

  3. 相同的也提供了两种构造方法

// 直接配置 item header 和 content 的 layout 资源
public SectionRvAdapter(Context context,
LinkedHashMap<IH, List<ID>> originDatas,
int headerLayoutId, int contentLayoutId) // 仅仅加入 header 的 layout 资源,content的资源能够使用addType方法加入
public SectionRvAdapter(Context context,
LinkedHashMap<IH, List<ID>> originDatas,
int headerLayoutId)
final LinkedHashMap<ItemHeader, List<Content>> map = new LinkedHashMap<>();
adapter = new SectionRvAdapter<ItemHeader, Content>(this, map,
R.layout.item_header_header,
R.layout.item_header_content) {
@Override
protected void onBindItemHeader(BaseViewHolder holder, ItemHeader data, int pos, int type) {
holder.setText(R.id.info1, data.getItemHeaderTitle());
} @Override
protected void onBindContent(BaseViewHolder holder, Content data, int pos, int type) {
TextView tv = (TextView) holder.getView(R.id.tv);
}
};

监听事件

支持单击、双击和长按事件

三种事件

public interface OnItemListener<D> {
// 单击事件
void onClick(int pos, BaseViewHolder holder, D data);
// 长按事件
void onLongPress(int pos, BaseViewHolder holder, D data);
// 双击事件
void onDoubleClick(int pos, BaseViewHolder holder, D data);
}

实现须要的事件

抽象类的实现,能够选择性的实现须要的方法

public abstract class SimpleItemListener<D> implements OnItemListener<D> {

    @Override
public void onClick(int pos, BaseViewHolder holder, D data) { } @Override
public void onLongPress(int pos, BaseViewHolder holder, D data) { } @Override
public void onDoubleClick(int pos, BaseViewHolder holder, D data) { }
} adapter.setItemListener(new SimpleItemListener <GuideData>() {
@Override
public void onClick(int pos, BaseViewHolder holder, GuideData data) {
Toast.makeText(mContext, "单击事件", Toast.LENGTH_SHORT).show();
} @Override
public void onLongPress(int pos, BaseViewHolder holder, GuideData data) {
Toast.makeText(mContext, "长按事件", Toast.LENGTH_SHORT).show();
} @Override
public void onDoubleClick(int pos, BaseViewHolder holder, GuideData data) {
Toast.makeText(mContext,"双击事件", Toast.LENGTH_SHORT).show();
}
});

SectionRvAdapter 事件

adapter.setItemListener(new SimpleItemListener<ItemModel>() {
@Override
public void onClick(int pos, BaseViewHolder holder, ItemModel data) {
// 当是Content数据类型
if (data.getRvType() == AbsAdapter.TYPE_ITEM_DEFAULT) {
Content content = (Content) data.get();
Toast.makeText(SectionAdapterTest.this, content.contentTitle, Toast.LENGTH_SHORT).show();
}else{
// 当是ItemHeader数据类型
}
}
});

数据更新

为了简化数据更新的方法。内置了数据更新的部分方法

内置更新方法

// 插入一条数据
public void insert(int pos, D data)
// 更新数据,isUpdate为false时仅仅会加入数据不会更新显示
public void notifyDataSetChanged(List<D> data, boolean isUpdate)

分页更新方法

// 简化分页载入的更新。调用该方法实现增量更新,不会所有刷新。isAllData为true时表示data是所有数据。为false时表示是追加的数据
public void appendTailRangeData(List<D> data, boolean isAllData)

SectionRvAdapter 追加更新

// SectionRvAdapter比較特别,须要使用单独的更新方法

// 使用SectionRule配置数据时,使用此方法更新
public void updateDataAndItemHeader(List<ID> data)
// 使用Map配置数据时,使用此方法更新
public void updateDataAndItemHeader(Map<IH, List<ID>> map)
// 分页载入更新数据时调用,仅支持使用SectionRule配置数据
public void appendSectionTailRangeData(List<ID> data)

Module

使用Module配置附加功能,眼下有HFModule(加入Header和Footer)、LoadMoreModule(预载入很多其它)

加入 Header 和 Footer

  • HFModule
// 生成和加入module
HFModule hfModule = new HFModule(mContext,
R.layout.header_footer_headerly,
R.layout.header_footer_footerly, mRv);
adapter.addHFModule(hfModule);
// 更改Header 和 Footer的数据,相似数据的配置,你能够在实现的方法里绑定数据和监听事件
adapter = new SimpleRvAdapter<HFModel>(mContext, hfModels, R.layout.header_footer_item) {
@Override
public void onBindHeader(BaseViewHolder header) {
super.onBindHeader(header);
} @Override
public void onBindFooter(BaseViewHolder footer) {
super.onBindFooter(footer);
}
};
// 当仅仅想加入Header或Footer时,使用常亮HFModule.NO_RES表示没有资源
HFModule hfModule = new HFModule(mContext,HFModule.NO_RES,
HFModule.NO_RES, mRv); // 隐藏Header 和 Footer
public void setFooterEnable(boolean footerEnable)
public void setHeaderEnable(boolean headerEnable)

预载入很多其它

  • LoadMoreModule

new LoadMoreModule(int preLoadNum, OnLoadMoreListener lis),preLoadNum表示提前几个Item进行预载入,preLoadNum越大预载入的越提前

载入数据完毕之后须要调用mLoadMoreModule.finishLoad();结束本次载入,保证下次载入能够生效

        // 触发之后1500秒后载入数据
LoadMoreModule loadMoreM = new LoadMoreModule(4, new OnLoadMoreListener() {
@Override
public void onLoadMore(final LoadMoreModule mLoadMoreModule) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
List<LoadMoreModel> tempData = new ArrayList<LoadMoreModel>();
for (int i = 0; i < 9; i++) {
tempData.add(new LoadMoreModel("new is " + i));
}
adapter.appendTailRangeData(tempData, false);
mLoadMoreModule.finishLoad();
}
}, 1500);
}
});
adapter.addLoadMoreModule(loadMoreM);

其它

adapterId 区分

为了区分不同的适配器,生成了adapterId,用来检測当前RecyclerView使用的是不是这个adapter

public boolean isThisAdapter(RecyclerView rv)

Sample


//内部类实现
quickAdapter = new TypeRvAdapter<Demo>(self, demos) {
@Override
public void onBindView(RvViewHolder holder, Demo data, int pos, int type) {
// 给控件绑定数据,必须实现
} @Override
public void onBindHeader(RvViewHolder header) {
//给Header绑定数据和事件,不须要能够不实现
} @Override
public void onBindFooter(RvViewHolder footer) {
//给footer绑定数据和事件,不须要能够不实现
}
}; //继承实现
public class MyAdapter extends TypeRvAdapter<Demo> { public MyAdapter(Context context, List<Demo> data) {
super(context, data);
} @Override
public void onBindView(RvViewHolder holder, Demo data, int pos, int type) {
// 给控件绑定数据,必须实现
} @Override
public void onBindHeader(RvViewHolder header) {
//给Header绑定数据和事件,不须要能够不实现
} @Override
public void onBindFooter(RvViewHolder footer) {
//给footer绑定数据和事件,不须要能够不实现
}
}

RecyclerView高速通用适配Adapter的更多相关文章

  1. 为RecyclerView打造通用Adapter

    ##RecycleView简单介绍 RecyclerView控件和ListView的原理有非常多相似的地方,都是维护少量的View来进行显示大量的数据.只是RecyclerView控件比ListVie ...

  2. 为RecyclerView打造通用Adapter 让RecyclerView更加好用

    原文出处: 张鸿洋 (Granker,@鸿洋_ ) 一.概述 记得好久以前针对ListView类控件写过一篇打造万能的ListView GridView 适配器,如今RecyclerView异军突起, ...

  3. RecyclerView的通用适配器

    本来这一个主题应该早就写了,只是项目多,属于自己的时间不多,所以现在才开动!! 前一段时间写了一篇文章,是关于ListView,GriView万能适配器,没有看过的同学,可以先看看那篇文章,然后在来学 ...

  4. RecyclerView打造通用的万能Adapter

    既然想做到通用那么现在摆在面前的就三个问题:数据怎么办?布局怎么办? 绑定怎么办?.数据决定采用泛型,布局打算直接构造传递,绑定显示效果肯定就只能回传. 1 基本改造 数据决定采用泛型,布局打算直接构 ...

  5. RecyclerView的通用适配器,和滚动时不加载图片的封装

    对于RecyclerView我们需要使用RecyclerAdapter,使用方式与ListViewAdapter类似,具体代码大家可以在网上搜索,这里就只教大家使用封装后的简洁RecyclerAdap ...

  6. RecyclerView更通用——listView的onItemClick,onLongItemClick,addHeaderView,addFooterView

    一.点击事件 setOnItemClickListener,setOnItemLongClickListener RecyclerView中虽然没有提供上面这两个接口,但是给我们提供了另外一个接口:O ...

  7. 设计通用的Adapter

    2019年3月18日 10:53:27 参照博文:Android 快速开发系列 打造万能的ListView GridView 适配器 一 BaseViewHolder public class Bas ...

  8. 通用的Adapter

    activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&qu ...

  9. wesome-android

    awesome-android Introduction android libs from github System requirements Android Notice If the lib ...

随机推荐

  1. Cordova cannot add Android failed with exit code ENOENT

    这可能是系统环境变量损坏了 解决方案:在系统变量path如果没用下面的变量就加上%SystemRoot%\system32; %SystemRoot%; %SystemRoot%\System32\W ...

  2. EF分页

    先来看看几个LINQ to SQL的几个函数. Take 说明:获取集合的前n个元素:延迟.即只返回限定数量的结果集. var q = (  from e in db.Employees  order ...

  3. 解决mssql localdb 中文乱码问题

    使用以下查询语句即可. alter database "E:\.Net Core\Database\hm.mdf" set single_user with rollback im ...

  4. COBBLER无人值守安装

    cobbler-自动安装系统 1.1 cobber简介 1.1.1 cobbler说明 Cobbler是一个Linux服务器安装的服务,可以通过网络启动(PXE)的方式来快速安装.重装物理服务器和虚拟 ...

  5. python基础-------函数(二)

    闭包函数与装饰器 一.闭包函数 闭包函数:函数内部定义函数,成为内部函数,该内部函数包含对外部作用域,而不是对全局作用域名字的引用那么该内部函数成为闭包函数 name='alex' # def fun ...

  6. Drools文档(六) 用户手册

    用户手册 基础 无状态的知识Session Drools规则引擎拥有大量的用例和功能,我们要如何开始?你无须担心,这些复杂性是分层的,你可以用简单的用例来逐步入门. 无状态Session,无须使用推理 ...

  7. key-value存储数据库--Redis

    1.简介 Redis是完全开源的ANSI C语言编写.遵守BSD协议,高性能的key-value数据库. 1.1特点 Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载 ...

  8. Luogu P1073 最优贸易

    题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双 ...

  9. Qt颜色下拉框

    上周为了用Qt写一个类似颜色下拉框的东西,查阅了网上的多数相关资料,依然没有我想要的.终于在周四的时候下定决心重写QCombobox类来实现功能,现在把它贴出来,望看到的人,批评指正.废话不多说,先上 ...

  10. Oracle存储过程和自定义函数

    新博客文章链接,欢迎大家评论探讨 概述 存储过程和存储函数是指存储在数据库中供所有用户程序调用的子程序叫存储过程.存储函数. 异同点: 存储过程和存储函数的相同点:完成特定功能的程序. 存储过程和存储 ...