Visibility values after rebuild
See original GitHub issueHello!
I need to keep track of the first time a some data is fully visible to the user (it doesn’t matter if it’s hidden and shown again multiple time later) and I’m using a OnModelVisibilityChangedListener
added to the model like this
new OfferModel_().id(offer.getId())
.onVisibilityChanged((model, view, percentVisibleHeight, percentVisibleWidth, heightVisible, widthVisible) -> {
if (percentVisibleHeight == 100 && percentVisibleWidth == 100) {
callbacks.resultViewFullyVisible(offer.getId());
}
}).addTo(this);
The first time the recyclerview is shown everything is working as expected. The problem is that when the data set is changed and the models are rebuilt, some views have an initial visibility different from the final, like 100% and 7% a few ms later. In this case, the new data are tracked as visible when in reality they’re only partially visible and shouldn’t be tracked. I think it’s due to the recycling of the views, but I don’t know if this is the intended behaviour and how to avoid this.
I did some logging on the visibility listener to better explain this. The logs contain
id
related to the data shown in the view,heightVisible
,percentVisibleHeight
,view.hashCode()
(to check if the view was used before, not sure if it’s the right thing to use for that though).
First time the data are shown: looks right
14:18:23.053 D/TEST - onVisibilityChangedListener: b12cxEGT, height=290 (100%) hash=62627501
14:18:23.054 D/TEST - onVisibilityChangedListener: 2c27QurT, height=290 (100%) hash=134837730
14:18:23.055 D/TEST - onVisibilityChangedListener: bf4fFYoT, height=290 (100%) hash=213794163
14:18:23.056 D/TEST - onVisibilityChangedListener: c30bVurT, height=290 (100%) hash=229336112
14:18:23.057 D/TEST - onVisibilityChangedListener: 1e10QYoT, height=126 (43%) hash=127957161
The recyclerview is hidden before the new data set is loaded, so every view becomes invisible. Seems right.
14:18:48.681 D/TEST - onVisibilityChangedListener: 1e10QYoT, height=0 (0%) hash=127957161
14:18:48.684 D/TEST - onVisibilityChangedListener: c30bVurT, height=0 (0%) hash=229336112
14:18:48.686 D/TEST - onVisibilityChangedListener: bf4fFYoT, height=0 (0%) hash=213794163
14:18:48.689 D/TEST - onVisibilityChangedListener: 2c27QurT, height=0 (0%) hash=134837730
14:18:48.693 D/TEST - onVisibilityChangedListener: b12cxEGT, height=0 (0%) hash=62627501
New data set:
14:18:51.382 D/TEST - onVisibilityChangedListener: 9097cNrT, height=126 (43%) hash=127957161
14:18:51.391 D/TEST - onVisibilityChangedListener: a5d94xoT, height=290 (100%) hash=229336112
14:18:51.398 D/TEST - onVisibilityChangedListener: c78eiTrT, height=290 (100%) hash=213794163
14:18:51.404 D/TEST - onVisibilityChangedListener: 9097cNrT, height=290 (100%) hash=127957161
14:18:51.405 D/TEST - onVisibilityChangedListener: c78eiTrT, height=21 (7%) hash=213794163 -----> this one is causing incorrect tracking because it was 100% few ms ago
All of this logs are without the user scrolling the list. Epoxy version: 3.7.0 Any suggestion or workaround? Thank you!
Issue Analytics
- State:
- Created 4 years ago
- Comments:8 (5 by maintainers)
I did not looked for the RV visibility yet but I guess it is caused by the same bug. Let me try to repro in your sample app.Actually I see, by RV is hidden you mean when the adapter change, not the RV’s visibility. So yes, same bug, it is basically sending the recycled view visibility attributes (too early, it’s before the final visibility, that’s the bug).
What happen :
First time the list is loaded:
height=290 (100%) hash=213794163
as the view is created, attached and laid out.Then the RV is hidden:
height=0 (0%) hash=213794163
0 is sent because the tracker detect the view was detached (but internally the view is still at 290px - 100%).Then a new set of data is loaded and the views are reused:
height=290 (100%) hash=213794163
is (wrongly) sent because this is the current view size whenonAttach
event occurs. Then it get re-layout andheight=21 (7%) hash=213794163
is sent.I am trying to find the best fix to solve this issue…
Hi @eboudrant, thanks for looking into this.
The list doesn’t have a fix length and the items on screen depends on how big is the screen device. Sometimes there are one or two horizontal carousel above the vertical list with other view types (I’ll need to track them as well, but now I’m focusing on the views in the vertical list).
Not really. These logs are taken before any scroll from the user, so I’d expect something like the first set of logs: a few views 100% visible and one only partially shown.
I’ve created a really small example to show the issue: https://github.com/AgneseBussone/EpoxySample. It logs the visibility in the logCat in a similar way. Feel free to tweak it as you need 😃 It loads three sets of data and you can switch from one to another using the app bar menu. To reproduce the issue, try to load set 1, 2 and 3 without scrolling (it just makes easier to see it)
This is the first set: the count of four is correct.
Then the second set (correct):

Then the third set, with the wrong count (it should be 4):