RxJava get cache then wait for network calls to update - android

Can we have any workaround for this problem.
I'm trying to get cache to show to user first then call network api to update current data (if device have network connection)
How we can combine them together ?

If you can use your cache and api as observables whose emits same class of items, you are probably looking for merge method.

Related

RxJava2 repository cache with observers concurrency

I have a repository making a network call via a datasource.
I have two use cases that both call that reposository to get the resource but are making different treatments.
Those use cases are subscribing at the same time.
The behavior I want is to make the network call on first subscription, block the other ones and then cache the data to observers in queue.
For now I have a fetch method in the repository actually making the network call (called at one place in my code). I have a get method that return a behavior subject that is valued when the fetch method get data (the uses cases are observing this behavior subject).
I don't like having those two methods and I think it should be transparent. In an ideal case the use cases should call a single repository method and get data (the first one making the network call because cache is missing, the second one getting the cached data).
Is there a way to do this with RxJava ?

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:
If connected to the internet, fetch data and use Android Room to store for offline use
If not connected to the internet, check if data exists in Room. If exists, display it. If it doesn't exist, display an error message.
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.
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)
If the data is available in the Database, return it immediately.
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.
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.
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.

Can we chain multiple API calls or keep track of multiple calls being made at once?

I have 21 API calls that need to be made once the app gets to the splash screen. What my app does is as follows:
a> Make API call using retrofit's enqueue method.
b> once the response is available(call success) it stores data to local database using greendao. Inside app it only uses data from greendao databases. What I need is to keep track of the api call whether it failed or not. If failed retry. Also if there is a way to chain the requests can anyone mention them? I looked into rxjava which allows chaining upto 2 or 3 apis (as far as I know). Any help is much appreciated.
You can create IntentService which will run call.execute() code one by one.
This way you will call synchronous call to all apis.
Once all request completes send broadcast to activity or communicate with activity through other mechanism.

Firebase single value listener calls server even when local cache is available and has not changed

My Firebase database has setPersistenceEnabled=true. When offline all the listeners work fine and fetch data from the local cache.
But, when online, Firebase is making a network call each time I use a addListenerForSingleValueEvent on the same node, even though I have a local cache and nothing has changed on the server.
I have two items at the node I'm attaching the listener to, and I see the following reported after setting log level to debug. This network activity is repeated every time I use the listener while online, even within sub second delays. My understanding is that if Firebase has local data, then server calls won't be made. Any sync checks might happen in the background and with efficient network usage.
conn_18 - received data message: {r=20, b={s=ok, d={}}}
conn_18 - received data message: {r=21, b={s=ok, d=}}
I am trying to aggressively reduce network usage on my app, and any suggestion to stop/reduce Firebase network activity would be very helpful.
Been digging into this myself.
As far as I can tell, the second call you are experiencing is simply the network saying "Hey, there's no updates", and you're not charged for any reads.
As far as reducing the network activity, I think this is just how it works, and how you want it to work (its the actual listening part of the listener). If you don't want that, use a getDocument call, rather than a listener.
This is based on a few things:
When you look at snapshot.metadata.isFromCache (iOS SDK) for a query, the call will come twice. first from cache and then from the server. However, if you print a statement under snapshot.documentChanges, ONLY the cached call will print.
I did an experiment re-loading a view in iOS ~20 times. I also made on small change to my data. I then waited 5-10 minutes and looked at the usage on: https://console.cloud.google.com/firestore/usage. My total read count went up by 3, which means I was only charged for the update. Reloading the view a bunch of times was NOT charged.

Robospice: return cached data when network is down

I am starting to use robospice for an application which has to function in regions with changing connectivity.
How would I achieve that robospice would automatically return the cached data when the network is down?
Thanks
Ben
I have not worked with Robospice at all. But from what I can tell it looks like the request class allows you to specify AcceptingDirtyCache by calling
request.setAcceptingDirtyCache(boolean isAcceptingDirtyCache)
there was a thread about this on github that talks about this very problem.
Also not sure since I have never used robospice but you should be able to call CacheManager.loadDataFromCache() to load any data that exists in the cache. So you could utilize this function whenever you need to make a request but the network is down.

Categories

Resources