RecyclerView.Adapter и GridLayoutManager с spanCount больше 4 непрерывно воссоздает ViewHolders - PullRequest
0 голосов
/ 26 октября 2018

Я работаю с 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?

1 Ответ

0 голосов
/ 26 октября 2018

Я воспроизвел вашу проблему с помощью этого кода (копируемый, файлы ресурсов не требуются):

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)
...