RxAndroid, event bus and activity life cycle

I found several articles on how RxJava / RxAndroid can replace event buses (e.g. otto )

Quote from the first article:

Otto from the square officially abandoned the previous days. In the Android world, we can welcome something like "EventBusses are dead RxJava long."

There is one thing I miss, though:

One of the privileges of event buses is that they help a lot with the Activity lifecycle, since you don’t need to manage call logging / recording manually (and thus avoid memory leaks)

Stream example:

  • Activity subscribes to an event to receive songs (e.g. SongsAvailableEvent)
  • We request songs (we make a network request)
  • We will change the average device orientation request
  • Creates an activity and a new one, which is also subscribed to SongsAvailableEvent
  • The new action receives the event and updates the user interface, and the old activity (which is now dead) does not receive the event (yay!)

In the above articles, you can see that this stream is "resolved" by RxAndroid / RxJava, but when using Rx, you still need to subscribe / unsubscribe to Monitoring manually when changing the device orientation. Moreover, if I want to "reuse" the request made in Observable, I need to somehow save it so that I subscribe to the same Observable in a new action (I'm not quite sure how to do this, but this is not the point: )).

My question is whether this problem is easily solvable with pure RxAndroid / RxJava, or I still need to use Rx with an event bus / Rx extension using something like RxLifecycle (which complicates the situation since I do not control my Observables in presentation layer)?

+5
source share
2 answers

Your onDestroy activity can always cause you to unsubscribe.

For work on reusing a query, look at Loaders and LoaderManager. EventBus and RxJava for a solution that was never needed.

0
source

I would venture to say that there is no way out of the fact that at some point in the chain the Observable should be tied to the life cycle of some object of the Android platform, such as Activity. Also, since you did not mention this as a partial solution, I assume that you are avoiding the use of saved snippets. If you create and save a link to the Observable only within the framework of your activity, it is impossible for the results of the query in flight to withstand the destruction of the Activity and automatically subscribe to a new one. In addition, at some point, either during a change of orientation, or at the end of an Activity in the middle of a network request, your Observable will leak a link to an Activity (via its subscribe() callback) if it does not unsubscribe from Activity onDestroy()

I found that RxLifecycle is easy to use. There is a method in my base class Activity :

 public <T> Observable.Transformer<T,T> bindLifecycleOnMainThread() { return o -> o.compose(lifecycleProvider.bindToLifecycle()) .observeOn(AndroidSchedulers.mainThread()); } 

lifecycleProvider is created according to the instructions for RxLifecycle, depending on how you create your provider. This particular implementation uses bindToLifecycle() instead of specifying an explicit life cycle event, so its use is contextual. Calling it during onResume will cause it to terminate on onPause . Calling it during onStart will terminate it on onStop . Calling it at another time will cause it to terminate on onDestroy . Since this subscription will update the user interface, it should only be seen in the user interface thread.

This can then be used in an Activity as follows:

 yourObservable.compose(bindLifecycleOnMainThread()) .subscribe(event -> handleEvent(event)); 

Now, where did this observation come from? Well, there is no magic yet, and if you want the Observable to have a longer life than the Activity, this means that the Observable must be held by a component that lives longer than the Activity. There are many ways to do this, but your specific use case fits well with the new ViewModel library included with Android Architecture . If you were using ViewModels, your ViewModel would have a method that starts a network request and would have PublishSubject or PublishRelay that would highlight SongsAvailableEvent objects (although I recommend exposing it to your Activity only as an Observable<SongsAvailableEvent> , not an object, for good encapsulation!). Your ViewModel will make a network call and redirect the results to your object.

Finally, your activity, when it is created, will immediately receive its ViewModel from the ViewModel registry and subscribe to the Observable<SongsAvailableEvent> (which is the object / relay) that the ViewModel opened, and then bind it to the Activity lifecycle, as in the above an example. ViewModel will withstand any changes in the orientation of the Activity, and therefore will be observed. The observer will never try to deliver the event to the destroyed Activity, and the new action will immediately begin to listen to the events.

I believe this strategy promotes good encapsulation, since Activity does not relate to how a network request is created, and it does not relate to how an Observable source is created. The only way that Activity manipulates an Observable is to choose what happens when it receives the event and bind the subscription to the Activity lifecycle.

It can be infinitely modified and refined by composing your Observables, but it should help you with that.

0
source

Source: https://habr.com/ru/post/1262775/


All Articles