2021年1月20日星期三

RecyclerView item inserted with item updated is skipping inserted animation

I have a basic RecyclerView setup on a chat-like app and I have hit an issue with the item animations.

The project is making use of Room with Paging 3 and DiffUtils for the RecyclerView adapter, so this is all automated, but the core of the problem can be simplified to this:

  1. When I send a new message, that message is added to the RecyclerView
    • here the adapter is triggering notifyItemInserted or notifyItemRangeInserted which causes the entire message list to shift up softly and the new message fades in after
  2. I scroll the list to the bottom so the new added item becomes visible
  3. When I receive a read status from the server I update the status of that message
    • here the adapter is triggering notifyItemChanged or notifyItemRangeChanged which has no default animations on its own, it just updates the item with the new information

All of this is working well on its own, but the problem is when I receive a status update from the server faster than the insert animation has a chance to finish. When that happens the notifyItemChanged or notifyItemRangeChanged kicks in and skips the animation initiated by notifyItemInserted or notifyItemRangeInserted. The list till shifts upwards, but the fade in no longer happens, instead the item is instantly made visible all the while the list is still shifting up, overlaying the item previously occupying that last position causing an ugly visual experience.

I can kinda "cheat" by delaying the step in 2. to engage after the animation is supposedly over, but then it introduces another visual issue if the user sends multiple messages quickly or receives them in the same fashion.

first second
enter image description here enter image description here

In this example there are 2 recyclerviews set up with the same adapter slightly changed to make it easier to compare the issue in the same action.

The left recyclerview is not doing any update when an item is inserted, but it is the behavior I expect to display even if I update the item during the item insertion animation. On the right recyclerview is the actual problem, as you can see new items are showing in full over the old ones before they have a chance to move out of the way. The first example recording has scroll to bottom with no delay after the item is inserted, the second example has a delay that matches the insertion animation duration.

Reminder: this is just a manual example, the real application in my case is being done automatically via the integration I mentioned above, I am not the one in control of when the notifyItem* calls are made at any point.

How can I make sure the insert animation does not get interrupted even if I am updating the item data in the middle of the animation?

https://stackoverflow.com/questions/65820901/recyclerview-item-inserted-with-item-updated-is-skipping-inserted-animation January 21, 2021 at 11:46AM

没有评论:

发表评论