RecyclerView AsyncListDiffer и состояние согласованности источника данных теряются с onClickListener

У меня есть источник данных (в этом примере это просто var myState: List)

      class MainActivity : AppCompatActivity() {
    var generation: Int = 0
    var myState: List<User> = emptyList()
    val userAdapter = UserAdapter {
        val index = myState.indexOf(it)
        if (index == -1)
            println("🔥 not found")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val recycler = findViewById<RecyclerView>(R.id.rvContent)
        recycler.layoutManager = LinearLayoutManager(this)
        recycler.adapter = userAdapter
        Thread {
            while (true) {
                generateNewData()
                Handler(mainLooper).post {
                    userAdapter.submit(myState)
                }
                sleep(3000L)
            }
        }.start()

    }

    fun generateNewData() {
        generation++
        myState = (0..5000).map { User("$generation", it) }
    }
}

У меня есть RecyclerView и AsyncListDiffer, подключенный к нему

      data class User(val name: String, val id: Int) {
    val createdTime = System.currentTimeMillis()
}

data class UserViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
    fun bindTo(user: User, action: (User) -> Unit) {
        val textView = view.findViewById<TextView>(R.id.title)
        textView.text = "${user.name} ${user.id} ${user.createdTime}"
        textView.setOnClickListener { action(user) }
    }
}

class UserAdapter(val action: (User) -> Unit) : RecyclerView.Adapter<UserViewHolder>() {
    val differ: AsyncListDiffer<User> = AsyncListDiffer(this, DIFF_CALLBACK);

    object DIFF_CALLBACK : DiffUtil.ItemCallback<User>() {

        override fun areItemsTheSame(oldItem: User, newItem: User): Boolean {
            return oldItem.id == newItem.id
        }

        override fun areContentsTheSame(oldItem: User, newItem: User): Boolean {
            return oldItem == newItem
        }

    }

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

    override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
        val user = differ.currentList[position]
        holder.bindTo(user, action = action)
    }

    fun submit(list: List<User>) {
        differ.submitList(list)
    }

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

У меня OnClickListener привязан к каждому элементу RecyclerView

      {
    val index = myState.indexOf(it)
    if (index == -1)
        println("🔥 not found")}

Этот слушатель проверяет, существует ли элемент, по которому был выполнен щелчок, в источнике данных, и, если нет, выводит его на консоль. Каждые несколько секунд данные в источнике изменяются и отправляются в AsyncListDiffer с помощью метода submitList, иногда внутренне он использует другой поток для сопоставления данных и передачи этих различающихся данных в RecyclerView, а это занимает некоторое время; Если я начинаю щелкать элементы без остановки, и событие щелчка происходит в то же время, когда разница вставляет новые данные, то я перехожу в несогласованное состояние.

Итак, как с этим справиться?

  1. Игнорировать щелчок с несогласованными данными? (Минусы: пользователь может видеть какое-то странное поведение, например, элемент списка не сворачивается / расширяется, не происходит навигации и т. Д.)
  2. Попытаться найти похожий элемент в новых данных по отдельным полям (позициям и т. Д.) И использовать его? (Минусы: такие же, как 1., но с меньшей вероятностью)
  3. Блокировать события OnClickListener до тех пор, пока данные не будут согласованы как в Recycler, так и в источнике данных? (минусы: то же, что и выше, а также задержка с действием, выполняемым пользователем, до тех пор, пока данные снова не станут согласованными)
  4. Что-то другое? Как лучше всего это решить?

0 ответов

Другие вопросы по тегам