簡體   English   中英

recyclerview 適配器如何知道調用 onCreateViewHolder?

[英]How does the recyclerview adapter know to call onCreateViewHolder?

我剛剛看到這個示例 class 用於 Recyclerview 的適配器,我有點困惑它是如何知道調用 onCreateViewHolder、onBindViewHolder 等的,只是將項目 object 添加到列表中? 它與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)
    }

}

項目 Class:

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

每當 Adapter 需要為 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)
    }
}

我反向迭代,因此當您迭代和刪除項目時,刪除的索引是穩定的。

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

這個 function 是關鍵,它通過知道總共有多少來知道要創建多少,要綁定多少。 創建的ViewHolder的數量更多地取決於一次可以在屏幕上容納多少View

當您有不同的視圖類型時,這會變得更加復雜,因為隨着視圖類型的變化,有時必須創建比從一開始就需要的更多的ViewHolder

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM