16

I'm still figuring out RxJava and using it to do some networking stuff with Retrofit 2. Been trying it our for a a couple days and like that the code looks more readable now but have come across an issue that I cant seem to figure a way around.

I am trying to perform a login (which returns an API token) and then use this token to fetch some initial data all in the same chain so that the output of the chain is the token + data. To do this I call my API service with a

apiClient
    .login()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .flatMap(token -> getData(token))
    .subscribe(new Subscrber<Bundle>() {...});

This seemed fine, but I also wanted to show a progress bar when starting and stopping the chain. So I added a .doOnSubscribe() and a .doOnUnsubscribe() to this as well. However I noticed that after orientation change the fragment that I was trying to hide the progress bar is always null.

So I searched and came across the RxLifecycle lib that seemed like it would help and I now .cache() and unsubscribe from the event chain. But I cant figure out how to subscribe to the same event again in onCreate() after this? I think I'm missing something pretty basic and would appreciate any help with this.

source.rar
  • 8,002
  • 10
  • 50
  • 82
  • 1
    The best thing you can do i split your logic and implement `MVP` pattern. After that you `Presenter` class (which ideally should be singleton per view instance) will handle all the networking and keep the on view rebuild after screen rotation. Actually there is pretty neat library that allows to use `MVP` pattern based on rxJava https://github.com/konmik/nucleus (it's really small). Even if you don't want to use it, you can get an idea how it can be implemented – Than Dec 14 '15 at 11:33
  • hmm.. ok so I guess I need to read up on a good MVP implementation as well before going down the RxJava route... – source.rar Dec 14 '15 at 15:50
  • 1
    `MVP` can make your code much more cleanier and will solve this problem, but maybe it's not the solution you are looking for (it's not that easy to switch whole app architecture to MVP) (that's why I didn't post it as answer). I'm sure you there is a way to do it without `MVP` using either 3rd party lib or some nice patterns but I did not have any clean solution. Treat my above comment as "how others are handling similiar problem". – Than Dec 14 '15 at 15:55
  • 1
    Another thing you may want to look at: https://github.com/kaushikgopal/RxJava-Android-Samples#rotation-persist – Than Dec 20 '15 at 21:55

2 Answers2

1

You don't necessarily have to use any architecture pattern to accomplish that. Though any MVP/MVC are nice things for concerns separation, testing etc, making your Controller/Presenter/DAO an application-wide singleton, which keeps up memory through whole application's life is not exactly a good idea.

Here's a sample project using retained fragment instance and RxJava - https://github.com/krpiotrek/RetainFragmentSample

The main idea there is to use Fragment with setRetainInstance(true) called, which protects it from being destroyed on orientation change, and store your Observable in there. Here's how you handle that in Activity/Fragment onCreate

protected void onCreate(Bundle savedInstanceState) {
    if (savedInstanceState == null) {
        // first run, create observable
        mInfoObservable = createInfoObservable();
        // set Observable in retained fragment
        RetainFragmentHelper.setObject(this, getSupportFragmentManager(), mInfoObservable);
    } else {
        // following runs, get observable from retained fragment
        mInfoObservable = RetainFragmentHelper.getObjectOrNull(this, getSupportFragmentManager());
    }

    // subscribe 
    mInfoObservable.subscribe(...);
}

Keep in mind that your Observable has to cache last value, one way is to use cache() operator.

krp
  • 2,247
  • 17
  • 14
0

You need to make sure that you subscribe to the same Observable instance that is returned from .cache(). Typically you would store this instance somewhere in a Singleton (like the Application class), a retained fragment or an Android Service.

Jeroen
  • 3,399
  • 1
  • 22
  • 25