I'm having a problem with the following methods:
int firstVisibleItemPosition = gridLayoutManager.findFirstVisibleItemPosition();
int lastVisibleItemPosition = gridLayoutManager.findLastVisibleItemPosition();
My goal: save analytic data about what items the user have viewed.
In order to do that, I'm calling this methods in two different scenarios:
every time scrolling turned to "idle" state, and checking what are the visible items. in that case I'm getting the expected indexes.
when the RecyclerView
become "visible" to the user.
now that's when the problem starts. I would expect that when the fragment containing the recylcerView is passed onResume()
then calling findLastVisibleItemPosition()
will return the visible items. but it return -1, in that case. I guess it have something to do with the asynchronous loading of the recyclerView + adapter internal items initialization relative to the fragment/activity lifecycle.
by postpone this code by a few milliseconds - findLastVisibleItemPosition()
returns the right indexes. but I don't want to postpone hard coded using handler + delayed runnable, because scheduling delayed runnable is a work-around to what I really want to do: detect when the recycler view finished inflating and drawing to the screen all the views that can feet inside of it..
so my questions are basically:
how can I detect when the RecyclerView finished all the initialzation/measuring/inflating and drawing of it child items that feet into screen? (before any user interaction..).
is there any reliable good practice way to know exactly what items within' the recycler view is really shown on screen?
What about configuration changes? If the user changes the screen orientation, the visible items will change too. The fact is, visible items are changing constantly according to the state of the RecyclerView
, the loaded data, the scroll position and the current screen configuration.
The best thing you can probably do is creating a class which constantly keeps track of the superset of visible items, by making it implement the ItemDecoration
interface which is called each time a RecyclerView
gets redrawn on screen, and have this component send stats periodically. You would reattach it to the new RecyclerView
instance on configuration change (preserving its state).
So for example this component could keep track of the minimum and maximum visible positions. At first it will be -1 for both. Then after the data is loaded and the first items are shown on screen, the ItemDecoration
will be called again and first visible item position will now be 0 and last visible item position will now be N. After scroll, the values will change again. You would only keep the min value of FirstVisibleItemPosition and the max value of LastVisibleItemPosition in order to get the superset. After X seconds without changes, or if the user navigates back from the Activity, you would record and send these numbers.