I am making a network using Retorfit
+ RxJava2
and I want to cache the response for 30 seconds. Any calls made after 30 seconds interval should get the latest results from server. I tried doing this using Replay
operator but it still makes a network call every time I call subscribe. I am not an expert in RxJava so maybe my understanding of using Replay
for caching like that is wrong.
public Observable<Name> getName() {
return retrofitBuilder.getName()
.subscribeOn(Schedulers.io())
.replay(30, TimeUnit.SECONDS,Schedulers.io())
.autoConnect();
}
and I am calling the above code like this:
service.getName()
.subscribe(new Consumer<Name>()
{
@Override
public void accept(Name name) throws Exception
{
Log.d("getName", "Name: " + name.toString());
}
}
, new Consumer<Throwable>()
{
@Override
public void accept(Throwable throwable) throws Exception
{
Log.d("getName", throwable.getMessage());
}
});
UPDATE: My apology if I didn't explain my question clearly. What I want is caching on a particular request instead of caching it on HttpClient
level which applies the caching strategy to all the request being made through it. In the end I would like to define different caching expiration for different request when needed. Not all my request needs caching for small duration. I was wondering if I could do just that.
Appreciate your help in this.
Try to look at okhttp interceptors.
Add CacheInterceptor:
And add it and cache to your OkHttp Client like this:
The are 2 problem with your approach:
Observable
each time you callservice.getName()
you're creating a new instance ofObservable
, you should keep the same replayed instance and give to the caller outside the same instance each time it callsservice.getName()
.replay
with 30 seconds, will replay the sequence emitted by the sourceObservable
over the last 30 sec, meaning after cache expiration time, you will get nothing as your request happened more than 30 sec ago. it doesn't mean that theObservable
will restart automatically after this period.In order to cache for specific period, you basically need to invalidate the cached response after cache period, and perform new request after this period, that's mean you should control your subscribe, and do it there.
You can achieve it with something like that:
with defer you can return the right
Observable
according to cache expiration status, so every subscribe happened within the cache expiration will get cachedObservable
(usingcache()
) - meaning request will be performed only once. after cache expiration, additional subscribe will trigger new request and will set a new timer to reset the cache expiration.