赞
踩
事情是由工作中的一个新项目里的一个页面里的频繁改需求引起的,原来只是不同布局,上下滚动,没有类似网格排布的UI,所以我用ScrollView写的,里面包ConstraintLayout,没有问题,滚动丝滑。后面需求改了,有个地方是列表,塞一个RecyclerView进去,没问题,滚动依旧丝滑。后面,又加另一个列表,再塞一个RecyclerView进去,滚动依旧丝滑,但是,发现这个RecyclerView只显示几个item,后面的不显示了,我还各种断点查看列表数据源和Adapter是不是有问题,结果是没问题,然后给RecyclerView设置一个超大的高度,列表就显示完全了,看来还是RecyclerView嵌套在ScrollerView的问题。后面百度了一下,在RecyclerView外包一层RelativeLayout,显示就完整了,滚动也没问题。开开心心提测,后面,发现列表数据量多的时候,整个页面ANR了。
怎么办呢?重构页面肯定是要的,普通办法是一个RecyclerView根据类型加载对应的ViewHolder,一想起来,好麻烦,心累。但是,现在可是2023年啊,有没有可能谷歌给了新的api呢?jetpack都重构了安卓框架,总该给点新花样吧?果然是有的,就是ConcatAdapter(据说是RecyclerView1.2.0开始有的,之前是另外的名字,但是功能是一样的),就是把多个Aapter整合到一块。然后就跟ArrayList一样add添加Adapter,UI就根据添加顺序显示,adapter各管各的UI和数据,耦合性大大降低。
使用也是超级简单,RecyclerView直接setAdapter()把ConcatAdapter添加进去,然后再把不同布局的adapter添加进去,最后concatAdapter.notifyDataSetChanger()即可。
由于我用的是Jetpack+Kotlin,mvvm是github大佬在Jetpack基础上封装的,我的写法特别简单,可能对应不上你们的代码,仅做参考。
xml布局只需传ConcatAdapter进去,设置滚动方向就好,不需要设置item布局:
- <androidx.recyclerview.widget.RecyclerView
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_marginTop="46dp"
- android:layout_marginBottom="53dp"
- adapter="@{adapter}"
- app:layoutManager="com.kunminx.binding_recyclerview.layout_manager.WrapContentLinearLayoutManager"
- android:orientation="vertical"
- app:layout_constraintLeft_toLeftOf="parent"
- app:layout_constraintRight_toRightOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"/>
如果里面的子布局仅仅是标题,列表的头部ui,这种简单layout,且不需要更新数据,它的adapter也非常简单,areItemsTheSame和areContentsTheSame都是为true,刷新列表的时候不更新,不然会闪烁一下。
- class OrderListHeadAdapter @JvmOverloads constructor(
- context: Context,
- layout: Int = R.layout.adapter_orde_list_head,
- onItem:DiffUtil.ItemCallback<Int> = object : DiffUtil.ItemCallback<Int>(){
- override fun areItemsTheSame(oldItem: Int, newItem: Int) = true
- override fun areContentsTheSame(oldItem: Int, newItem: Int) = true
- }
- ):SimpleDataBindingAdapter<Int,AdapterOrdeListHeadBinding>(context,layout,onItem){
- override fun onBindItem(
- binding: AdapterOrdeListHeadBinding?,
- item: Int?,
- holder: RecyclerView.ViewHolder?
- ) {}
- }
添加这个adapter的时候,一定要传个list,而且长度不为0,所以adapter的数据类型使用Int还是比较方便的,使用其他类型也可以。
concatAdapter.addAdapter(OrderListHeadAdapter(requireContext()).apply { submitList(mutableListOf(0)) })
列表部分也是一样,平时普通的该咋设置咋设置,再创建添加进去即可。添加完了记得刷新
concatAdapter.notifyDataSetChanged()
清空列表,只能遍历remove掉adapter,目前没找到合适的api。
比切换ViewHolder方便太多,耦合性大大降低。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。