question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Injecting items into PagedListEpoxyController makes RecyclerView jump upon update

See original GitHub issue

We have a list of items that come from the database. Based on their date we generate header models that we insert in the list using addModels.

We scroll for a bit, up to a point where the last item of the first page is at half of the screen (this means the second page will be loaded). Now we update some item in the database to trigger a new PagedList. Upon submitting this new PagedList to epoxy, AsyncPagedListDiffer will diff the items and update the list. This new list will not start at position 0 (that’s how paging library works). This means that the initial items will be removed from the RecyclerView. Without adding extra models, the RecyclerView will be able to keep it’s position. You will see exactly the same items on screen. As soon as we add extra items, the RecyclerView isn’t able to keep the same position on screen and we see a jump when it removes the initial items.

Now I have two untested theories for this:

  1. It’s because only the item list gets diffed so the RecyclerView doesn’t account for the extra items height (is this right?). In that case we have to diff the model list instead of the item list.

  2. It’s because of:

override fun onModelBound(
    holder: EpoxyViewHolder,
    boundModel: EpoxyModel<*>,
    position: Int,
    previouslyBoundModel: EpoxyModel<*>?
  ) {
    // TODO the position may not be a good value if there are too many injected items.
    modelCache.loadAround(position)
  }

Somehow, the controller would have to take the additional injected items into account.

I’m more inclined towards theory 1. But I don’t know if the premise for that option is valid.

I’ll try to build a small project to replicate the issue. Maybe @yigit can shed some light on this?

Thanks

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:2
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

3reactions
PedroAlvaradocommented, Jun 16, 2019

This is likely related to the google issue below. See the comments at the bottom of that issue.

https://issuetracker.google.com/issues/123834703

Long story short, if you are using an ItemKeyedDataSource, on invalidation(e.g., update on the list), the current position on the screen will be ignored when computing the items/pages to load. This can lead to “jumps” to other parts of the list as the paging library will attempt to load pages that are not the ones in the current screen context.

I consider this a bug in Android’s paging library. Everyone using ItemKeyedDataSource will eventually run into this issue with no recourse other than overriding complex library code.

If you are to chase this down, find implementations of the DataSource.InvalidatedCallback interface and notice that most of them boil down to a initializeKey = PagedList.getLastKey() followed by the instantiation of a new PagedList with setInitialKey(initializeKey). The getLastKey() method effectively runs the code below, leading to “jumps” as the current position is ignored.


    final Key getKey(int position, Value item) {
        if (item == null) {
            return null;
        }

        return getKey(item);
    }

0reactions
PedroAlvaradocommented, Jun 28, 2019

@yigit Can you provide some input into this issue? The participants on this issue have provided a fair amount of detail on why this issue happens along with steps to reproduce. I understand that there is a fair amount of changes coming up in Android Pagination(coroutines, etc) and it will be great that an answer to this issue is provided as part of this iteration. Thank you for your help.

Read more comments on GitHub >

github_iconTop Results From Across the Web

PagedList RecyclerView jumping after pagedList invalidation
The way we solved this issue is, UI only listens from Room Database as a single source of truth. This issue is not...
Read more >
Updating data in an Android RecyclerView | by Suragch
Update the data set; Notify the adapter of the change. The following examples will show how to do that. Insert single item. Add...
Read more >
RecyclerView scrolls down on data update using Paging with ...
Scrolling n pages down and then updating an item in the list appears to cause the page to reload. This causes the RecyclerView...
Read more >
Flexible RecyclerView Adapter with MVVM and Data Binding
A RecyclerView Adapter that can handle multiple item types ... do some transformations on the raw data to make it suitable for our...
Read more >
Using the RecyclerView | CodePath Android Cliffnotes
Customizable Item Layouts - ListView can only layout items in a vertical ... call notifyDataSetChanged() on the entire adapter to update the entire...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found