美文网首页
ExpandableRecyclerView实现方式

ExpandableRecyclerView实现方式

作者: youxiaochen | 来源:发表于2023-01-15 00:12 被阅读0次

前言:

根据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.0'
}
源码地址 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

相关文章

网友评论

      本文标题:ExpandableRecyclerView实现方式

      本文链接:https://www.haomeiwen.com/subject/jbewcdtx.html