androidkotlinandroid-workmanageroffline-caching

Logic to update network requests using Work Manager


I have an application which fetches data from an API. SO basically, right now, the app works as such:

I did some research online on how to implement an efficient offline storing policy and Google suggests to use Work Manager to queue requests and then send it when connected.

I actually want to know how to implement this ? (not the code but the logic, i.e should i schedule requests everyday to the API or every time it's connected to the internet ?)

If someone with experience with offline apps could help would be great.

My network requests are done through Retrofit and i already create a class that perform calls to the API.


Solution

  • Keep in mind WM (work manager) is designed to perform operations when certain conditions are met (e.g.: the user has enough battery, the display is off, etc.). So this may end up with your data not being updated when you need it. WM is good for operations you want to happen but are not critical to occur "right now". I'd say always use the Room DB as the single source of truth. If the data is in room, show it, if it's not, fetch it, if you can't, well, you tried. Send a message to the user. You can use a NetworkConnectivityListener to monitor connectivity and check if you have a pending query (you could store the parameters of this query in your Room database in another table for ease of use). So you'd query the DB, obtain the pending queries (if any) and execute them, update the data, and let the ViewModel/Repository decide if there's a context to show this data (UI).

    I feel like you are very close to achieve what you need.

    So in other words:

    UI: Observes its viewModel for some sealed class xxx state to tell it what to do (show an empty list, show an error, pass data to a recyclerview adapter, etc.).

    ViewModel: Using its viewModelScope.launch { ... } will call a repository.fetch(...) or similar. Your viewModel will fetch this data when the Fragment tells it to do so (e.g. the user pressed a button) or on some lifecycle event (onStart for example).

    The Repository in this case normally exposes a flow (if you can use the experimental api) or a suspend function that can perform the following actions (that can vary depending on your business rules)

    1. If the data is available in the Database, return it immediately.
    2. If the data is old (or we still want to refresh it), then perform the network API (if there's connectivity to do so). If there's No connectivity, you could store this "pending" query in the database for later. You could also check if you have a pending query before doing any of this, perhaps it's outdated or perhaps you need to execute it.
    3. In any case, once the query goes through, you insert the results in the database, and call the same method you used in step 1.
    4. Don't forget to update your "pending" query if you had one (or if you use this).

    With WorkManager, you could schedule the "fetch data from API" part to happen at some point (so your data will be kept more up to date), but I all really depends on the use-cases you have.