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.

Sticky headers displays wrong header or crashes after dataset change

See original GitHub issue

StickyHeaderLinearLayoutManager does not handle adapter dataset changes correctly.

Specifically, it doesn’t handle properly the case where a set of changes notifications includes an insert followed by one or more deletes or moves. This causes the wrong view to be used as sticky header in some cases, and in rare cases it can also cause an out of bounds error because the code tries to access data outside the range of the adapter.

The flawed logic is located in the child class HeaderPositionsAdapterDataObserver. As long as items are deleted or moved, everything works fine. But when onItemRangeInserted() is called, there is a problem: the code tries to access the adapter immediately to check if there are headers in the new inserted elements, but instead it must wait for the other adapter updates to be dispatched before accessing the adapter data to be able to compute the adapter positions correctly.

Because adapter updates are asynchronous, multiple calls to notify* can be done in a row for a single change of adapter data. It’s only after that, during the next layout pass that the adapter data can be accessed.

Here is a simple example to illustrate the issue:

  • An adapter initially contains 4 items
  • The items list is updated with a new list of 4 items: a new item has been added at the end and the first item has been deleted
  • To notify the changes, DiffUtil will call notifyItemInserted(4, 1) immediately followed by notifyItemDeleted(0, 1)
  • When onItemRangeInserted() is called, HeaderPositionsAdapterDataObserver in StickyHeaderLinearLayoutManager will immediately try to access the adapter element at position 4 to check for new headers. But this position is out of range: the list only contains 4 elements. The adapter needs to wait for the following call to onItemRangeRemoved() to be able to compute the adapter positions correctly. The adapter should only be accessed asynchronously during the next layout pass.

Because of this, sticky headers are unstable and cannot be used with DiffUtil. Only notifyDataSetChanged() works reliably.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:11 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
cbeylscommented, Sep 27, 2021

My version is heavily modified and doesn’t depend on Epoxy anymore. For example, I’m passing the adapter directly in the constructor. Feel free to check the changes I made and see if you can backport them in Epoxy: https://gist.github.com/cbeyls/db4351870e493a817bf0f4fd84e2b598

0reactions
samuelchoucommented, Sep 16, 2022

I did a little bit more research on it.

  • It turns out that, when managing index list (of StickyHeaders), it is hard to maintain all of their accuracy.

For example, consider an index list

2, 3, 5 ,7, 11

when inserting a new (non-SH) item at index 4, it have to be modified into

2, 3, 6, 8, 12

and situation become more complex when including SH and more :

2, 3, 5, 7, 11
- insert SH[5]: -> 2, 3, 5, 6, 8, 12
- remove range [4-5]: -> 2, 3, 4, 6, 10
- insert SH[1], SH[5] -> 1, 3, 4, 5, 6, 7, 12
  • And, changing List to Set doesn’t reduce the risks.
  • So…I’m now considering other solution.

So far, I think Set<SH-ID> might be a solution. It only turns into Set<SH-index> (dynamically) when using. But I haven’t fully-researched this solution yet.

Any suggestion or idea is welcome. (I’m also looking forward to someone else fixing this problem 😆 )

Read more comments on GitHub >

github_iconTop Results From Across the Web

java - Sticky Header Recyclerview Not working with ArrayList ...
I want to create recycleview with Sticky headers , I can make recyclerview with header and it is working perfectly fine but when...
Read more >
6 Common Google Data Studio Problems and How to Fix Them
Solution. Reformat dates in the data source into a format Data Studio understands. It may help to change the heading.
Read more >
Fixes or workarounds for recent issues in Outlook for PC
[FIXED] Error when trying to create or edit contacts in Outlook: You don't have permission to create an entry in this folder.
Read more >
Common WordPress Errors – WordPress.org Forums
If you receive a warning that WordPress cannot modify header information and headers are already sent, it usually means that you have spaces...
Read more >
Bug listing with status RESOLVED with resolution FIXED as at ...
status:RESOLVED resolution:FIXED severity:normal · Bug:3 - "poedit-1.1.5.ebuild" ... Bug:620 - "The prozilla package download site has changed.
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