【问题标题】:RecyclerView.Adapter and GridLayoutManager with spanCount great than 4 continuously recreates ViewHoldersSpanCount 大于 4 的 RecyclerView.Adapter 和 GridLayoutManager 不断重新创建 ViewHolders
【发布时间】:2018-10-26 10:30:34
【问题描述】:

我正在使用 GridLayoutManager,但遇到了意外的 RecyclerView 行为。如果 spanCount 大于 4,则 RecyclerView 在滚动时不断地重新创建 ViewHolders。

    override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.main_activity)

       val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
       recyclerView.layoutManager = GridLayoutManager(this, 7)
       recyclerView.adapter = Adapter()
   }

   private class Adapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
       //continuously invokes while scrolling:
       override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
           val view:View = TextView(parent.context).apply {
               text = "Hello!"
           }
           return object : RecyclerView.ViewHolder(view) {}
       }

       override fun getItemCount(): Int = 3500

       override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {}
   } 

如何解决并强制 RecyclerView.Adapter 重用 ViewHolders?

【问题讨论】:

  • 我认为你不应该在 onCreateViewHolder 中创建 Text 对象。你是一个 ViewHolder 类
  • @Vitali 在onBindViewHolder 方法中似乎缺少代码。您能否完成代码,以便我们了解这里发生了什么?目前,由于理想情况下它是空的,因此您不会看到任何应该显示的内容。
  • 查看本教程以获得更好的理解。 android.jlelse.eu/…

标签: android android-recyclerview android-viewholder recyclerview-layout gridlayoutmanager


【解决方案1】:

我用这段代码重现了你的问题(可复制粘贴,不需要资源文件):

class RecActivity : AppCompatActivity() {
    lateinit var recyclerView: RecyclerView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        recyclerView = RecyclerView(this)
        setContentView(recyclerView)
        recyclerView.layoutManager = GridLayoutManager(this, 7)
        recyclerView.adapter = Adapter()
    }

    inner class Adapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
        var vhCount = 0
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            val txtView = AppCompatTextView(this@RecActivity)
            txtView.tag = vhCount++.toString()
            txtView.gravity = Gravity.CENTER
            title = vhCount.toString()  // display # of created VHs in title
            return object : RecyclerView.ViewHolder(txtView){}
        }

        override fun getItemCount() = 3500

        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            (holder.itemView as TextView).text = "$position (${holder.itemView.tag})"
        }
    }
}

问题是没有足够的视图来填写RecycledViewPool 中的整行。默认情况下,每个 ViewType 只有 5 个项目,因此具有 7 个宽行会在滚动时强制创建更多 ViewHolders。要解决此问题,只需像这样增加RecycledViewPool 的大小(在onCreate 中):

recyclerView.layoutManager = GridLayoutManager(this, 7)
recyclerView.adapter = Adapter()
// add line below: 0 is default itemViewType, 14 is two rows of items which should be enough
recyclerView.recycledViewPool.setMaxRecycledViews(0, 14)

【讨论】:

    猜你喜欢
    • 2021-05-29
    • 2021-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-25
    • 1970-01-01
    • 1970-01-01
    • 2022-08-12
    相关资源
    最近更新 更多