Introducing RVTimeTracker - RecyclerView Time Tracker

An Android library designed to precisely track the time spent by users viewing items in a RecyclerView.

Introducing RVTimeTracker - RecyclerView Time Tracker

Understanding User Engagement in Android

As Android developers, we’re constantly looking for ways to understand user behavior within our apps. A critical aspect of this understanding is knowing how much time users spend viewing individual items in a RecyclerView. This insight is invaluable for optimizing the user experience and tailoring our app to meet their needs.

Why RVTimeTracker?

The idea for RVTimeTracker was sparked during a weekend of curiosity. We’re often exposed to ad impressions being measured extensively, but what about tracking the time users spend on regular items within our app? It got me thinking, what if we could gather data on how users engage with each item in a RecyclerView.

RVTimeTracker is designed to accurately measure and provide insights into user engagement at a granular level. It allows you to precisely track the time users spend viewing items in a RecyclerView, giving you valuable data to enhance your app’s UI/UX.

How RVTimeTracker Works?

At its core, RVTimeTracker operates by comparing the new (latest) visible items in the RecyclerView with the previous state of visible items. It tracks the differences based on the unique ID of each data item, enabling it to monitor when an item goes out of the visible screen.

Initialization of RVTimeTracker

Integrating RVTimeTracker is a breeze. By simply adding a few lines of code, you can start tracking user engagement effortlessly.

Add dependency inside your project build.gradle file

implementation 'com.example.rvtimetracker:rvtimetracker:1.0.0'

Initialization: Start by initializing RVTimeTracker with your RecyclerView and desired parameters. Check the demo in the Github project link mentioned at the end of the article.

// Initialize the RecyclerView Time Tracker library in your activity or fragment
RVTimeTracker.init (
    recyclerView = binding.recyclerView,
    trackItem = { trackInfo ->
        // Lambda function to be executed when any item moves out of the visible screen
        Log.i("TrackData", trackInfo.toString())
    }
)

You get the TrackInfo object that contains the view tag, position of item and duration of item viewed in milliseconds. See below Logcat

------------Logcat--------------
TrackInfo(viewTag=d73bbb42-c43b-4c5c-9b2b-7e9fb7c6f66b, itemPosition=0, viewDuration=5055)
TrackInfo(viewTag=e9c758ff-4eae-423a-afa0-3dd7b18e4e2a, itemPosition=1, viewDuration=5882)
TrackInfo(viewTag=571a4cb8-0b54-4f5a-bfd1-f98444c97049, itemPosition=2, viewDuration=6595)

To fine tune some parameter based on the individual need, following parameter can be passed white initializing RecyclerView Time Tracker (all the params are optional)

  1. minTimeInMs (default = 0): Minimum time in milliseconds a view needs to be visible to be tracked. Value should be greater than 0

  2. minHeightInRatio = 0.45,(default = 0.5): Minimum height ratio a view should have to be tracked. Value should be between 0 and 1

  3. dataLimit = 8,(default = 10): Number of data after which “trackAll” lambda block will be invoked with the list of tracked data.

  4. trackItem = Lambda function to be executed when any item moves out of the visible screen. Contains TrackInfo (data class containing view duration, position, and view tag of the recycler view item)

  5. trackAll = Lambda function to be executed when the dataLimit is reached or after the onStop lifecycle method of the RecyclerView context is called. Contains list of TrackInfo)

RVTimeTracker.init(
    recyclerView = binding.recyclerView, // The RecyclerView to be tracked for item view times.
    minTimeInMs = 1000, // (optional, default = 0): Minimum time in milliseconds a view needs to be visible to be tracked. Value should be greater than 0
    minHeightInRatio = 0.45, // (optional, default = 0.5): Minimum height ratio a view should have to be tracked. Value should be between 0 and 1
    dataLimit = 8, // (optional, default = 10): Number of data after which "trackAll" lambda block will be invoked with the list of tracked data.
    trackItem = { trackInfo -> // Lambda function to be executed when any item moves out of the visible screen. (Contain TrackInfo)
        Log.i("TrackData", trackInfo.toString())
    },
    trackAll = { trackInfoList -> // Lambda function to be executed when the dataLimit is reached or after onStop lifecycle method of the RecyclerView context is called. (Contains List<TrackInfo>)
        for (item in trackInfoList) {
            Log.i("TrackDataAll", item.toString())
        }
    }
)

Automatic Tracking: RVTimeTracker tracks items as soon as the screen goes to the background or when items are removed from the list. This ensures comprehensive engagement data, even during transitions.

View Tags for Meta Data: Utilize the power of view tags to send metadata associated with each item. The viewTag acts as a key for storing tracking information. It provides a way to pass additional information, maintaining the uniqueness of each tag based on the data item in the list. This unique tag allows for easy association of time with each data item.

// Inside onBindViewHolder
holder.itemView.tag = item.id // Set a unique view tag for each item

Contribute to RVTimeTracker

RVTimeTracker is an open-source project, Kindly share your feedback, report issues, or contribute to further improve this library.

Link to library:

Github code:

https://github.com/khushpanchal/RVTimeTracker