RecyclerView使用和原理

幻昼 2021年07月21日 277次浏览

基本使用

  1. 实现Adapter和ViewHolder

    继承RecyclerView.Adapter,设置ViewHolder泛型,ViewHolder一般放在Adapter的内部类

  2. 编写ViewHolder和Adapter

    实现Adapter 和ViewHolder的抽象方法

    这里使用ViewBinding,得去build.gradle的android {}标签下开启

    viewBinding {
        enabled = true
    }
    

    Adapter例子:

    class WordAdapter(var dataSet: List<Word>) : RecyclerView.Adapter<WordAdapter.WordViewHolder>() {
    
        override fun getItemCount() = dataSet.size
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WordViewHolder {
            // 可以根据 viewType 生成不同的Holder,让列表内容多样化
            return WordViewHolder.create(parent)
        }
    
        override fun onBindViewHolder(holder: WordViewHolder, position: Int) {
            val item = dataSet[position]
            holder.bind(item.word)
        }
    
    
        class WordViewHolder(private val binding: RecyclerviewItemBinding) :
            RecyclerView.ViewHolder(binding.root) {
    
            fun bind(text: String?) {
                binding.textView.text = text
            }
    
            companion object {
                fun create(parent: ViewGroup): WordViewHolder {
                    val binding = RecyclerviewItemBinding.inflate(LayoutInflater.from(parent.context))
                    return WordViewHolder(binding)
                }
            }
        }
    }
    
  3. RecyclerView设置Adapter

    val wordAdapter = WordAdapter(ArrayList())
    val recyclerview = binding.recyclerview
    recyclerview.adapter = wordAdapter
    
  4. RecyclerView设置布局管理器

    recyclerview.layoutManager = LinearLayoutManager(this)
    

优缺点

优点

有回收和复用,速度快,效率高

缺点

需要额外的空间实现缓存机制,不过问题不大

复用机制

对照着图看代码

流程图

RV复用

时序图

RecyclerView_reuse

回收机制

流程图

RV回收

时序图

RecyclerView_recycle

布局流程

dispatchLayoutStep1

  1. Adapter的更新;
  2. 决定该启动哪种动画;
  3. 保存当前View的信息(getLeft(), getRight(), getTop(), getBottom()等);
  4. 如果有必要,先跑一次布局并将信息保存下来。

dispatchLayoutStep2

真正对子View做布局的地方。

  1. 计算锚点,以锚点开始填充RecyclerView(其实就是执行fill方法)。
  2. 执行fill方法,判断RecyclerView是否还有空间,如果有,执行layoutChunk方法,直至填充满。
  3. layoutChunk方法中,寻找到当前要添加的子view,add到RecyclerView中。
  4. 对子view进行measure和layout。

dispatchLayoutStep3

为动画保存View的相关信息; 触发动画; 相应的清理工作。

其实dispatchLayoutStep3()就是做了一些收尾工作,将一些变量重置,处理下动画。

mState.mLayoutStep

  • 初始化为STEP_START
  • 执行完dispatchLayoutStep1后,mState.mLayoutStep = State.STEP_LAYOUT;
  • 执行完dispatchLayoutStep2后,mState.mLayoutStep = State.STEP_ANIMATIONS;
  • 执行完dispatchLayoutStep3后,mState.mLayoutStep = State.STEP_START;