【问题标题】:How does the recyclerview adapter know to call onCreateViewHolder?recyclerview 适配器如何知道调用 onCreateViewHolder?
【发布时间】:2022-01-01 13:40:19
【问题描述】:

我刚刚看到了 Recyclerview 适配器的这个示例类,我对它如何知道仅通过将 Item 对象添加到列表中来调用 onCreateViewHolder、onBindViewHolder 等感到有点困惑? 它与notifyItemInserted(items.size - 1) 行有关吗? 是每当调用此方法时,都会为该项目调用 onCreateViewHolder 方法,还是? 适配器:

class ListAdapter (
    private val items: MutableList<Item>
) : RecyclerView.Adapter <ListAdapter.ListViewHolder>() {

    class ListViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
        return ListViewHolder(
            LayoutInflater.from(parent.context).inflate(R.layout.list_items, parent, false)
        )
    }

    override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
        val currItem = items[position]

        holder.itemView.apply {
            tv_item.text = currItem.title
            cb_item.isChecked = currItem.checked

            crossItem(tv_item, currItem.checked)

            cb_item.setOnCheckedChangeListener { _, isChecked ->
                crossItem(tv_item, isChecked)

                currItem.checked = !currItem.checked

                items.removeAll { item ->
                    item.checked
                }
                notifyDataSetChanged()
            }
        }
    }

    override fun getItemCount(): Int {
        return items.size
    }

    private fun crossItem (itemText: TextView, checked: Boolean) {

        if (checked){
            //dk wtf paint flags is
            itemText.paintFlags = itemText.paintFlags or STRIKE_THRU_TEXT_FLAG
        }
        //else remove
        else {
            itemText.paintFlags = itemText.paintFlags and STRIKE_THRU_TEXT_FLAG.inv()
        }
    }

    fun addItem (item: Item){

        items.add (item)

        notifyItemInserted(items.size - 1)
    }

}

物品类别:

data class Item (
    val title: String,
    var checked: Boolean = false
)
{
}

【问题讨论】:

    标签: android kotlin android-recyclerview


    【解决方案1】:

    每当适配器需要为 RecyclerView 提供一个新的视图来绘制时,它都会检查它的池中是否有一个未使用的 ViewHolder。如果没有,它会调用onCreateViewHolder(),以便创建一个。然后它为来自任一源的 ViewHolder 调用 onBindViewHolder(),以便可以在添加到布局之前准备包含的视图。

    如果您调用notify 方法之一,则会触发它刷新受影响的项目行。它将所有已删除的行返回到 ViewHolder 池,然后按照上述步骤获取新行所需的视图。如果您使用notify...changed 方法,则只需对适用的行使用onBindViewHolder()。当您使用核选项notifyDataSetChanged() 时,它会将所有项目返回到池中。

    当 RecyclerView 首次显示时,或者当布局调整大小时,这些操作可能会触发显示更多行的需要。当您滚动列表时,滚动出屏幕的项目将返回到 ViewHolder 池中,而当新项目滚动到视图中时,需要从池中创建或获取 ViewHolder,如上所述。

    顺便说一句,这看起来很难看,因为即使只删除了一些项目,它也会刷新整个列表:

    items.removeAll { item ->
        item.checked
    }
    notifyDataSetChanged()
    

    我建议这样做,以便您获得良好的过渡:

    for (i in items.indices.reversed()) {
        if (items[i].checked) {
            items.removeAt(i)
            notifyItemRemoved(i)
        }
    }
    

    我反向迭代,因此在您迭代和删除项目时,删除的索引是稳定的。

    【讨论】:

      【解决方案2】:
      override fun getItemCount(): Int {
          return items.size
      }
      

      这个函数是关键,它通过知道总共有多少来知道创建多少和绑定多少。创建的ViewHolders 的数量更多取决于屏幕上一次可以容纳多少Views。

      当您有不同的视图类型时,这会变得更加复杂,因为随着视图类型的变化,有时它必须创建比一开始所需的更多的ViewHolders。

      notify... functions 只是让Adapter 知道它需要“重新查看”List

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-07
        相关资源
        最近更新 更多