RecyclerView多种布局排布

        事情是由工作中的一个新项目里的一个页面里的频繁改需求引起的,原来只是不同布局,上下滚动,没有类似网格排布的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布局:

如果里面的子布局仅仅是标题,列表的头部ui,这种简单layout,且不需要更新数据,它的adapter也非常简单,areItemsTheSame和areContentsTheSame都是为true,刷新列表的时候不更新,不然会闪烁一下。

class OrderListHeadAdapter @JvmOverloads constructor(
    context: Context,
    layout: Int = R.layout.adapter_orde_list_head,
    onItem:DiffUtil.ItemCallback = object : DiffUtil.ItemCallback(){
        override fun areItemsTheSame(oldItem: Int, newItem: Int) = true
        override fun areContentsTheSame(oldItem: Int, newItem: Int) = true
    }
):SimpleDataBindingAdapter(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方便太多,耦合性大大降低。

       

你可能感兴趣的:(android)