ExpandableRecyclerView实现方式

前言:

根据ExpandableListView的原理实现的ExpandableRecyclerView,并根据RecyclerView的刷新机制增加Group,Child的相关刷新和查询功能, 并在其基础上加入PositionDatadata缓存
RecyclerViw之ExpandableRecyclerView
RecyclerViw之StickyRecyclerView
RecyclerView之WheelView
RecyclerView之BannerPager

先看功能图和效果图

刷新效果图.gif

布局图
测试demo.apk包下载

一:实现原理

在查找adapterPosition对应的Group或者Child的groupPosition与childPosition基本与ExpandableListView一致
1. 看过ExpandableListView原码的应该都清楚, 在实现Expandable中主要逻辑就是要根据当前adapterPosition来找出对应的是Group还是Child, 而网上大多实现方式类似将每个组当成一个List, 再将整个Adapter当成多个List, 或者是将Group封装成Position, 在根据adapterPosition查找Group或Child时遍历, 这里分析下有哪些弊端
A:

查找Group或者Child , 既然是封装的List或者是Position在查找的时候, 这些列表所对应的adapterPosition已经相当是排序过的, 那么一定要用二分查找

B:

封装成List需要传入List,getItmCount会大量调用,每次都要计算itemCount

C.

在Adapter中getItemCount和getItemViewType方法会大量的调用, 而这些方法中又需要计算 getItemCount和getItemViewType, 在onBindViewHolder时也需要计算, 特别是在GridLayoutManager或者StaggeredGridLayoutManager布局时getItemCount和getItemViewType会大量重复调用

D.

在刷新时要加入单个组, 或者加入range组时, 大多都只能notifyDataSetChanged, 这个方法早已经被google警告了,建议使用其它的刷新机制性能会更忧如notifyItemRangeChanged, notifyItemRangeInserted,notifyItemRangeRemoved等

E.

在展开或者叠起时或者实际开发也会需要查找adapterPosition来获取Child或者Group信息, 或者通过groupPosition,childPosition查找adapterPosition这里又会大量的循环查找性能较差

F.

ExpandableListView的实现方式, ExpandableListView是将组信息封装成GroupMetada, 每一个要查找的position封装成PositionDatadata, 保存着adapterPositoin和groupPosition或者childPosition, 只保留展开的GroupMedata, 但是这种方式也只局限了LinearLayoutManager, 在Grid和StaggeredGrid时大量的调用getItemCount和getItemView时性能不好,因此需要加入position缓存

2. 缓存原理

这里的缓存不是LruCache, LinkedHashMap底层原理还是要通过hash & 操作查找到数组索引再链表或者红黑树遍历查找, 这里只根据adapterPosition & 操作找出数组索引位置中的缓存PositionMetadata, 在getItemViewType或者onBindViewHolder新的position
时直接复用PositionMetadata覆盖新的信息, 重复调用时直接使用,可以防止getItemViewType大量重复调用时的性能问题

3. 扩展

提供PositionMetadata所对应的GroupInfo和ChildInfo类, 在ExpandableRecyclerView中提供查找的方法并也是通过缓存的方式优先查找, 先重复利用的查找方式, 提供groupPosition和childPosition查找对应adaposition, 扩展如StickyRecyclerView

二 使用, 没有过度的封装, 支持ConcatAdapter,Header,Footer

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }  
}

dependencies {
    implementation 'com.github.youxiaochen:expandable-recyclerview:1.0.4'
}
源码地址 https://github.com/youxiaochen/expandable-recyclerview

ExpandableRecyclerView相关方法

ExpandableRecyclerView 常用方法 说明
expandGroup(int), isGroupExpanded(int) 组相关操作 展开, 是否展开
collapseGroup(int) 组相关操作 叠起, 是否叠起
setAdapter(ExpandableAdapter...) 适配器,支持ConcatAdapter
findGroupInfoByIndex(int),findGroupInfoByIndex(int,GroupInfo) 通过groupPos查找相GroupInfo, GroupInfo查找复用
findChildInfoByIndex(int,int),findChildInfoByIndex(int,int,ChildInfo) 通过groupPos,childPos查找ChildInfo, ChildInfo复用
findGroupInfoByPosition(int), findChildInfoByPosition(int) 通过Adapter position查找相关信息,可以是ConcatAdapter 支持info复用
findGroupInfoByBindingPosition(int), findChildInfoByBindingPosition(int) 通过ExpandableAdapter中的位置查找相关信息 ,info复用
static isGroupViewType(int) viewType类型是否为组
getCurrentTotalChildCount() 获取展开的所有Child数量
isGroupTypeByPosition, isGroupTypeByBindingPosition viewType类型是否为组
getHeaderCount(), getFooterCount 获取Header,Footer数量

ExpandableAdapter相关方法

ExpandableAdapter 常用方法 说明
getGroupCount, getChildCount adapter count
getGroupViewType , getChildViewType group, child viewType
onCreateGroupViewHolder, onCreateChildViewHolder group,child create ViewHolder
onBindGroupViewHolder, onBindChildViewHolder 支持 List<Object> payloads
getGroupItemId, getChildItemId ,hasStableIds setHasTableIds
groupCanClick 组不可点击时全部展开,
saveExpandableState 是否保存Expandable状态,关联onSaveStateInstance
getPositionPoolSize PositionMetadata缓存数量
onGroupStateChanged 展开或者叠时回调
onGroupViewRecycled, onChildViewRecycled Group,child ViewHolder recycler
onGroupViewAttachedToWindow, detached Group AttachedToWindow, detached
onChildViewAttachedToWindow, detached Child AttachedToWindow, detached
onAttachedToExpandableRecyclerView, detached AttachedToExpandableRecyclerView, detached
notifyDataSetChanged adapter 刷新
notifyGroupChanged, notifyGroupRangeChanged... 刷新Group是否连带刷新Child RangeChanged
notifyGroupInserted, notifyGroupRangeInserted Group insert, 顺insert时Child是否展开
notifyGroupRemoved, notifyGroupRangeRemoved Group remove rangeRemoved
notifyChildChanged, notifyChildRangeChanged Child 刷新 RangeChanged
notifyChildInserted, notifyChildRangeInserted... Child inserted RangeInserted
notifyChildRemoved, notifyChildRangeRemoved child remove RangeRemoved
registerAdapterDataObserver,unRegister... ExpandableAdapter注册与取消 观察者, 用于扩展(如StickyAdapter)
DataBinding使用及扩展可参考Demo中的extern包
源码地址 https://github.com/youxiaochen/expandable-recyclerview
RecyclerViw之ExpandableRecyclerView
RecyclerViw之StickyRecyclerView
RecyclerView之WheelView
RecyclerView之BannerPager

更多文章请关注:http://www.jianshu.com/u/b1cff340957c

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容