Some familiarity with RxJava is required for this article
Introduce a,
In this paper, the analysis idea is not to extract the code from the source code step by step tracking, but to ask questions, step by step to think about the solution, so as to learn the thinking essence of open source projects, rather than just to understand the specific implementation of the project. The author thinks that this way is more beneficial to readers to improve their own way of thinking and technical ability.
Open source projects
RxLifecycle address: github.com/trello/RxLi… . This project was created to prevent memory leaks caused by Subscription in RxJava. The idea is to automatically disconnect Subscription to prevent memory leaks by listening to the lifecycle of activities and fragments.
The basic usage is as follows:
myObservable
.compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY))
.subscribe();
Copy the code
MyObservable can be regarded as a time-consuming network request. By binding to Activityevent. DESTROY, once the Activity completes its DESTORY life cycle, the data will no longer be transferred to subscriber, that is, no processing or UI drawing will be performed on the data. Thus improving security.
Three, problem,
Android development often has a scenario like this:
- Send the network request -> 2. The server processes the request and returns the data -> 3. The client receives the data and draws the UI.
In the first two steps, there is usually no problem, but in the third step, when the data is returned to the client, if the page is already gone, then the UI cannot be drawn, which may lead to unintended problems. Therefore, to solve this problem, it is a good idea to automatically disconnect the network request data processing when the page is gone, that is, the data is returned without any processing.
Four, thinking
To achieve such a function, we can think of at least two parts:
- At any time to monitor
Activity
(Fragment
) and launch out; - In our network request, receive the life cycle and determine if the life cycle is bound by itself, e.g
Destory
, then break the process of data passing down.
Five, analysis,
As you can see, there is a core function to implement first: the ability to listen for Activity lifecycle events and transmit them externally, and to receive each lifecycle event and make a judgment. To do this, think of Subject in RxJava, which can both transmit and receive data.
Readers of Subject can skip this section.
How to understand Subject?
Easy. In RxJava, an Observable is a data transmitter. It sends data to the outside world, and then passes it to the Observer, the data receiver, after data processing such as map and flatMap. Therefore, regardless of the intermediate data processing, it can be seen that an Observable emits data externally, which is the beginning of data flow. An Observer receives data and is the end of the data flow.
What about Subject? Take a look at the source code:
* Represents an object that is both an Observable and an Observer. */
public abstract class Subject extends Observable implements Observer {}
Copy the code
First, it extends Observable, which means that the Subject has the ability to transmit data externally, i.e. from(), just(), etc. It implements Observer, implements data, onNext(), onCompleted, and so on.
After all, Subject is just an abstract class, so how do we use it?
Here is one of the simplest:
PublishSubject subject = PublishSubject.create();
// myObserver will receive "one" & "two" and onCompleted events
subject.subscribe(myObserver);
subject.onNext("one");
subject.onNext("two");
subject.onCompleted();
Copy the code
To do this, simply create a PublishSubject -> bind a myObserver, where the subject acts as an Observable. The data is sent to myObserver -> then the subject process receives two pieces of data, one and two -> Finally both of these data are passed to myObserver. Therefore, the role of subject is:
dataone
,two
=> (Observer) subject
(Observable) => myObserver
In simple terms, we feed the Subject data one and two, which in turn emits to myObserver.
BaseActivity listens for the life cycle
The basic idea is to create a PublishSubject object in BaseActivity and pass the life cycle event to the PublishSubject whenever the life cycle occurs. The implementation is as follows (only part of the life cycle is written, others are similar) :
class BaseActivity { protected final PublishSubject lifecycleSubject = PublishSubject.create(); @Override protected void onCreate(Bundle savedInstanceState) { lifecycleSubject.onNext(ActivityLifeCycleEvent.CREATE); . } @Override protected void onPause() { lifecycleSubject.onNext(ActivityLifeCycleEvent.PAUSE); . } @Override protected void onStop() { lifecycleSubject.onNext(ActivityLifeCycleEvent.STOP); . }... }Copy the code
In this case, we pass all lifecycle events to lifecycleSubject, or lifecycleSubject has received and has the ability to emit various lifecycle events.
8. Improve every Observable to receive life cycle and automatically disconnect itself
Our typical network request looks like this:
networkObservable
.subscribe(new Observer( handleUI() ));
Copy the code
NetworkObservable represents a common network request that receives network data and passes it to the Observer to draw the UI.
Now we want the networkObservable to listen for the Activity’s DESTORY event, disconnect the Observer when it happens, and not pass the network data back to the Observer to draw the UI. That is:
networkObservable
.compose(bindUntilEvent(ActivityLifeCycleEvent.DESTORY))
.subscribe(new Observer( handleUI() ));
Copy the code
Therefore, we need to implement
bindUntilEvent(ActivityLifeCycleEvent.DESTORY)
Copy the code
This method, how do you implement it?
We know that lifecycleSubject emits lifecycle events, so we can tell networkObservable to check the lifecycle emitted by lifecycleSubject. If the lifecycle emitted by lifecycleSubject is the same as the bound lifecycle event, it stops automatically.
Modify networkObservable
To automatically stop networkObservable, we can use operators
networkObservable.takeUntil(otherObservable)
Copy the code
Its function is to listen to the otherObservable. Once the otherObservable sends data, it automatically stops The networkObservable.
So when does the otherObservable send out data? Of course, lifecycleSubject launches when the lifecycle event emitted is equal to the bound lifecycle event.
otherObservable = lifecycleSubject.takeFirst(new Func1() { @Override public Boolean call(ActivityLifeCycleEvent activityLifeCycleEvent) { return activityLifeCycleEvent.equals(bindEvent); }});Copy the code
Which is the key to judge activityLifeCycleEvent. Equals (bindEvent); Once the conditions are met, the otherObservable sends data and networkObservable automatically stops immediately.
Merge lifecycle monitoring and networkObservable improvements
- Add it in BaseActivity
lifecycleSubject
And pass each lifecycle event on time tolifecycleSubject
-
Add a bindUntilEvent method to the BaseActivity:
@NonNull @Override public Observable.Transformer bindUntilEvent(@NonNull final ActivityLifeCycleEvent event) { return new Observable.Transformer() { @Override public Observable call(Observable sourceObservable) { Observable compareLifecycleObservable = lifecycleSubject.takeFirst(new Func1() { @Override public Boolean call(ActivityLifeCycleEvent activityLifeCycleEvent) { return activityLifeCycleEvent.equals(event); }}); return sourceObservable.takeUntil(compareLifecycleObservable); }}; }Copy the code
-
Requests improvements from networkObservable on any network
networkObservable .compose(bindUntilEvent(ActivityLifeCycleEvent.DESTORY)) .subscribe(new Observer( handleUI() )); Copy the code
Note:
- Mentioned in the article
networkObservable
Network requests, but this is not limited to network requests. Any time-consuming operation, such as file IO operations, can use this method to listen for the lifecycle and pause automatically. - The same is true for fragments.
Thank you very much!
wingjay
Welcome to pay attention to my lot: github.com/wingjay and my personal blog: wingjay.com and my Jane books: www.jianshu.com/users/da333… And twitter iam_wingjay: weibo.com/u/162589265… If you have any questions, leave me a comment or send me an email at [email protected]