Nimrod Dayan
Nimrod Dayan

Reputation: 3100

RxJava and Android: how to invalidate observable that use cache()?

I have an Activity that loads data using RxJava and Retrofit2. To prevent the request from being triggered every time a configuration change occurs, I use the cache() operator. This works well and I can see that the request is made only once. The problem is that from time to time, I need to make a new request to get fresh data. In another words, I need to invalidate the cache. How can I do that?

The activity is using a repository to make the request:

public class Repository {
private final PlaceholderApi api;
private Observable<List<Post>> obs;
private static Repository inst;

public static Repository instance() {
    if (inst == null) {
        inst = new Repository();
    }
    return inst;
}

private Repository() {
    HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> System.out.println(message));
    logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
    OkHttpClient okhttp = new OkHttpClient.Builder()
            .addInterceptor(logging)
            .build();
    Retrofit retrofit = new Retrofit.Builder()
            .client(okhttp)
            .addConverterFactory(MoshiConverterFactory.create())
            .baseUrl("http://jsonplaceholder.typicode.com/")
            .addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io()))
            .build();
    api = retrofit.create(PlaceholderApi.class);
}

public Observable<List<Post>> getAll() {
    if (obs == null) {
        obs = api.getPosts().cache();
    }
    return obs;
}
}

And the activity code:

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";
private Subscription sub1;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    sub1 = Repository.instance().getAll().subscribe(/* handle posts list */);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (sub1 != null && !sub1.isUnsubscribed()) {
        sub1.unsubscribe();
    }
}
}

Upvotes: 0

Views: 2601

Answers (2)

ajplumlee33
ajplumlee33

Reputation: 321

Here's an example using the OnSubscribeRefreshingCache wrapper class from Dave Moten's answer with your code:

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";
private Subscription sub1;
private OnSubscribeRefreshingCache<List<Post>> postCache;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        postCache = new OnSubscribeRefreshingCache(Repository.instance().getAll());
        sub1 = subscribe(Observable.create(postCache));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (sub1 != null && !sub1.isUnsubscribed()) {
            sub1.unsubscribe();
        }
    }

    private Subscription subscribe(Observable<List<Post> postObservable){
        return postObservable.subscribe(/* handle posts list */);
    }

    private void invalidateCache(){
        postCache.reset();
        sub1 = subscribe(Observable.create(postCache));
    }
}

Then call the invalidateCache() method during one of the Activity lifecycle methods or whatever works for you.

Upvotes: 1

Maks Tuev
Maks Tuev

Reputation: 31

Another way to solve your problem, is using OperatorFreeze (without operator cache), if you use persistent presenter. This operator can pause your Observable when configuration change occurs and resume it when activity recreated. You also don't need to store Observables in repository.

Upvotes: 0

Related Questions