View 使用 - RecyclerView(DiffUtil、ConcatAdaper)

本文详细介绍了RecyclerView的使用,包括设置LayoutManager、处理ViewType、点击事件、滚动操作以及去除边界水波纹。重点讲解了DiffUtil的使用,以提高数据更新的效率和性能,并介绍了ViewHolder的缓存机制,包括不同级别的缓存和存取流程。此外,还提到了ConcatAdapter用于合并多个Adapter以及如何自定义缓存策略。最后讨论了RecyclerView的性能优化技巧,如设置固定大小、预取项和控制滑动速度等。

一、概念

顾名思义不用操心 view 的复用,通过 LayoutManager 可设置数据的不同展示方式例如列表网格瀑布流,还可以设置条目添加删除的动画和间隔样式。

二、使用

2.1 基本使用

当复杂条目显示的时候,例如 position=1 的时候显示轮播图,那么 getItemCount() 返回 list.size() 要 +1,onBindViewHolder() 的时候拿数据 list.get(positon-1) 要减掉,分页加载在尾部添加一个 item 的话,getItemCount() 要再 +1。

class DemoAdapter(
    val context: Context
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    private val typeOne = 1
    private val typeTwo = 2

    private var dataList = mutableListOf<String>()  //数据不通过构造传入而是提供setter因为后期需要更新

    //创建viewholer的时候调用
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        //根据不同类型的Item返回不同的ViewHolder
        return if (viewType == typeOne) {
            DemoViewHolder.OneViewHolder(LayoutInflater.from(context).inflate(R.layout.item_one, parent, false))
        } else {
            DemoViewHolder.TwoViewHolder(LayoutInflater.from(context).inflate(R.layout.item_two, parent, false))
        }
    }

    //绑定viewholder的时候调用
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        //对不同类型的Item设置数据
        when (holder) {
            is DemoViewHolder.OneViewHolder -> {
                holder.tvName.text = dataList[position]
            }
            is DemoViewHolder.TwoViewHolder -> {
                holder.tvName.text = dataList[position]
            }
        }
    }

    //Item的总数
    override fun getItemCount(): Int {
        return dataList.size
    }

    //Item类型区分逻辑
    override fun getItemViewType(position: Int): Int {
        return if (position % 2 == 0) typeTwo else typeOne
    }

    //每一种布局都要写一个ViewHolder
    private sealed interface DemoViewHolder {
        class OneViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), DemoViewHolder {
            val tvName: TextView = itemView.findViewById(R.id.tvName)
        }
        class TwoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), DemoViewHolder {
            val tvName: TextView = itemView.findViewById(R.id.tvName)
        }
    }

    //上拉加载(往集合尾部追加)
    fun loadMore(list: List<String>) {
        dataList.addAll(list)
    }

    //下拉刷新(集合重新赋值)
    fun refresh(list: List<String>) {
        dataList = list.toMutableList()
    }
}
class DemoActivity : AppCompatActivity() {
    private lateinit var adapter: DemoAdapter
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
        recyclerView.layoutManager = LinearLayoutManager(this)
        val adapter = DemoAdapter(this)
        recyclerView.adapter = adapter
    }
}

2.2 点击回到顶部

recyclerView.scrollToPosition(0)

2.3 平滑的滚到某个位置

recycleView.smoothScrollToPosition(5)

2.4 去掉边界水波纹

android:overScrollMode="never"

2.5 解决嵌套滑动卡顿

        RecyclerView 嵌套 RecyclerView 的情况下会引起滑动冲突,默认情况下外层的RecyclerView可滑,内层不可滑。

        Nestedscrollview 是官方为了解决滑动冲突问题而设计的新的View,可以优化成 NestScrollView 嵌套 RecyclerView 方案。nestedScrollingEnabled 含义是支持嵌套滚动,默认情况下 RecyclerView 会随着 NestScrollView 滚动而滚动,放弃了自己的滚动,从而感觉到滞留卡顿。设为 false 来让 RecyclerView 能正常滚动。

android:nestedScrollingEnabled="false"

2.6 添加分割线

//系统自带分割线
recyclerView.addItemDecoration(DividerItemDecoration(this,DividerItemDecoration.VERTICAL))
//自定义分割线
val divider = DividerItemDecoration(this,DividerItemDecoration.VERTICAL)
val dividerDrawable = AppCompatResources.getDrawable(this, R.drawable.custom_divider)
dividerDrawable?.let {
     divider.setDrawable(it)
}
recyclerView.addItemDecoration(divider)

三、ConcatAdaper

假设 RecyclerView 内容被分为 Header、Content、Footer 三部分且它们的布局均不相同,通常是使用不同的 ViewType 来实现,现在是分别写三个Adapter,再通过 ConcatAdapter 顺序地组合多个 Adapter 并让它们显示在同一个 RecyclerView 中。

3.1 写三个xml布局:Header、Content、Footer

3.2 写三个继承自RecyclerViewer.Adapter的适配器

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值