如果我们使用DiffUtil.Callback,并做
adapter.setItems(itemList);
diff.dispatchUpdatesTo(adapter);
Run Code Online (Sandbox Code Playgroud)
我们如何确保添加新元素将滚动到新的位置.
我有一个案例,我看到项目消失,并在顶部创建一个新的第一个元素,但不可见.它会隐藏在顶部,直到您向下滚动以使其可见.在使用之前DiffUtil,我是手动实现的,在我知道我插入某个位置(在顶部)后,我可以滚动到.
如果您的RecyclerView获取新项目,最好使用notifyItemRangeInserted每个项目的唯一,稳定的ID,以便它可以很好地动画,而不会更改您看到的太多:
正如您所看到的,项目"0"(列表中的第一个)在我之前添加更多项目时保持在同一位置,就像没有任何更改一样.
这是一个很好的解决方案,当你在其他任何地方插入项目时,它也适合其他情况.
但是,它并不适合所有情况.有时,我从外面得到的是:"这里有一个新的项目清单,有些是新的,有些是相同的,有些是更新/删除的".
因此,我不能再使用notifyItemRangeInserted,因为我不知道添加了多少.
问题是,如果我使用notifyDataSetChanged,滚动会更改,因为当前项目之前的项目数量已更改.
这意味着您当前查看的项目将被视觉移到一边:
正如您现在所看到的,当我在第一个项目之前添加更多项目时,它们会将其推下来.
我希望当前可查看的项目尽可能多地保留,优先级最高的一个(在这种情况下为"0").
对于用户,他不会注意到当前项目之外的任何内容,除了一些可能的最终案例(删除当前项目以及之后的项目或以某种方式更新当前项目).它看起来好像我用过notifyItemRangeInserted.
我试图挽救当前的滚动状态或位置,后来恢复它,如这里,但没有解决方案存在的有固定这一点.
这是我尝试过的POC项目:
class MainActivity : AppCompatActivity() {
val listItems = ArrayList<ListItemData>()
var idGenerator = 0L
var dataGenerator = 0
class ListItemData(val data: Int, val id: Long)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val adapter = object : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
val inflater = LayoutInflater.from(this@MainActivity)
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder {
return object : RecyclerView.ViewHolder(inflater.inflate(android.R.layout.simple_list_item_1, parent, …Run Code Online (Sandbox Code Playgroud)