我有数据源(在那个例子中它只是一个 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")}
该侦听器检查单击的项目是否存在于数据源中,如果不存在,则将其输出到控制台。每隔几秒钟,源中的数据就会发生变化,并通过 submitList 方法推送到 AsyncListDiffer,在某些情况下,它在内部使用其他线程匹配数据并将差异数据传递给 RecyclerView,这需要一些时间;如果我开始不停地单击项目,并且当差异插入新数据时同时发生单击事件,那么我将进入不一致状态。
那么,如何处理呢?
- 忽略数据不一致的点击?(缺点:用户可以看到一些奇怪的行为,如列表项没有折叠/展开,没有导航发生等)
- 尝试通过单独的字段(位置/等)在新数据中找到类似的项目,并使用它?(缺点:与1相同。但概率较小)
- 阻止 OnClickListener 事件,直到 Recycler 和数据源中的数据一致?(缺点:与上述相同,并且还滞后于用户执行的操作,直到数据再次变得一致)
- 还有什么?解决这个问题的最佳方法是什么?