I have a screen with a list of products implemented using a recyclerview. I am looking for a way to check how much time the user spends looking at a certain item in the list. In this way I can know in which items is he interested so I can build him an "maybe interested in" list. More exactly..if a user stays on that item more than x seconds I retain that item id and do the rest... Any kind of ideea or help helps me alot. Thanks
-
Are you opening a new view for each item? If so, you could start a timer on opening and check the value on closing this view. Else, you could play with the "onScrollStateListener" for RecyclerView. – yennsarah Oct 20 '15 at 12:31
-
I use the ViewHolder pattern to display the views. I was thinking to use the OnBindViewHolder to get the position of the adapter (and this way the item) that is currentlly viewed. But for this approach I need to have an item covering the whole screen which can bring responsiveness issues. – Stef_ro89 Oct 20 '15 at 13:12
2 Answers
One option is to do something similar to Android: how to check if a View inside of ScrollView is visible? to determine which view is actually within the visible screen. It can be modified slightly to detect if the entire view is visible rather than only a portion.
You're probably also going to have to track the time started/stopped viewing in the recycle view's adapter.
-
Is there a way I can use getDrawingRect inside the adapter to get the recyclerview's visible bounds? – Stef_ro89 Oct 20 '15 at 13:56
I don't like idea to display user something like "maybe interested in" based on your logic. Because user has seen it already. It can be super annoying if I buy computer mouse and then I see it on every Activity I visit... I'd rather see some items from same category as most seen items but not the most seen items themself. That's why I highly suggest you to count time inside item details Activities (onStart
/onStop
methods)
But Answer can be something like this: See following methods:
RecyclerView.Adapter.onBindViewHolder
(View created because it is most likely going to be visible to user)
RecyclerView.Adapter.onViewRecycled
(View will be recycled - 100% not visible on screen)
You can create some Map
or another database column (don't know your project structure) to store item id's and timestamps from
private class MyHolder extends RecyclerView.ViewHolder {
long itemId;
long start;
public MyHolder(View itemView) {
super(itemView);
}
}
@Override
public void onBindViewHolder(BindingHolder holder, int position) {
holder.itemId = ...;
holder.start = System.currentTimeMillis();
}
@Override
public void onViewRecycled(BindingHolder holder) {
super.onViewRecycled(holder);
long currentTime = System.currentTimeMillis();
long difference = currentTime - holder.start;
// store result
map.put(holder.itemId, difference);
// to better match your needs update map item and do not overwrite it
}
This is not 100% solution, but is the simplest one.
To implement it inside Activities use same System.currentTimeMillis()
method inside onStart
and onStop
methods (or onResume
/onPause
). See Acticity lifecycle so that you know where you need it.

- 3,036
- 1
- 25
- 38
-
-
As you can see in the comment i made just 1 min before your answer this was the way I wanted to do it, but currently I have a problem because my item is not covering the whole screen so OnBindViewHolder will get 2 items even if one is barely visible. But onViewRecycled may help me... – Stef_ro89 Oct 20 '15 at 13:25
-
Or pick just first one if they are that large... users tends to look on top of the page not bottom – VizGhar Oct 20 '15 at 13:28
-
And how do I know which one is the first if onBind is called on every item the same way? – Stef_ro89 Oct 20 '15 at 13:40
-
`holder.getAdapterPosition()` returns you position in adapter... smallest available is first... – VizGhar Oct 20 '15 at 14:03
-
hmm on second though... the first visible item might be the item with only 1px visible displayed on top. You have to rethink this – VizGhar Oct 20 '15 at 14:05
-
The thing is that if I call holder.getAdapterPosition() inside onBindViewHolder it will get me the next item that is drawn (next than the one i'm interested if i scroll down and previous if I scroll up). I need the already visible one. – Stef_ro89 Oct 20 '15 at 14:19