![](/img/trans.png)
[英]Recyclerview not call any Adapter method: onCreateViewHolder, onBindViewHolder
[英]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.