In the context of the relationship between Rxjava Observer and subscriber, we mentioned that:
The results of subscribe (mobserver) and subscribe (Msubscriber) are different: subscribe (msubscriber) This subscription is not performed the second time the data is requested. The reason is that the subscription is automatically canceled after the first onnext, and subscribe (mobserver) does not appear.
Today we analyze the reason.
First take a look at the source code.
Subscription
There is an interface called subscription in the Rxjava that can be used to unsubscribe.
Public interface Subscription {
/**
* Stops "receipt of notifications on the" {@link subscriber} that is regist Ered when this Subscription
* is received.
* <p>
* This allows unregistering a {@link subscriber} before it has finished receiving all events (i.e. before
* oncompleted is called).
* *
void unsubscribe ();
/**
* Indicates whether this {@code Subscription} is currently unsubscribed.
*
* @return {@code true} if this {@code Subscription} is currently unsubscribed, {@code false} otherwise
*/
boolean isunsubscribed ();
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
As you can see from the above, we just need to call unsubscribe to unsubscribe, so how do we get a subscription object?
It's actually very simple:
The Observable.subscribe () method returns a subscription object, that is, each subscription will be returned.
Feel subscription is like an order, you will generate an order, and you can use this order to cancel the order. actual Combat
I first wrote the following code to test:
Subscription Subscription = Observable.just ("Hello Subscription")
. Subscribe (New action1<string> () {
@ Override public
void Call (String s) {
System.out.println (s);
}
});
System.out.println (subscription.isunsubscribed ());
Subscription.unsubscribe ();
System.out.println (subscription.isunsubscribed ());
1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9-10
The log that I want to output should be like this:
Hello Subscription
false
True
1 2 3 1 2 3
But the result was unexpected, and I was running after it:
Hello Subscription
true
1 2 3 1 2 3
Obviously I did not cancel the subscription ah, how is true?
Then I went into the source to explore the discovery:
In Observable.subscribe () Source:
Public final Subscription Subscribe (subscriber<. Super t> subscriber) {return Observable.subscribe (subscrib
Er, this);
Static <T> Subscription Subscribe (subscriber< Super t> Subscriber, observable<t> observable) { Validate and proceed if (subscriber = null) {throw new IllegalArgumentException ("Observer can
Not being null "); } if (observable.onsubscribe = = null) {throw new IllegalStateException ("Onsubscribe function can not
be null. ");
* * The Subscribe function can also be overridden but generally that's not the appropriate approach
* So I won ' t mention of the exception//new Subscriber so onStart it
Subscriber.onstart ();
* * https://github.com/ReactiveX/RxJava/issues/216 for discussion on "guideline 6.4:protect calls * To user code from within an Observer "* *
If not already wrapped if (!) (
Subscriber instanceof Safesubscriber)) {//Assign to ' observer ' so we return the protected version
Subscriber = new safesubscriber<t> (subscriber); }//The code below is exactly the same of unsafesubscribe but not used because it would//add a signif
Icant depth to already huge call stacks. try {//allow the hooks to intercept and/or decorate hook.onsubscribestart (observable, observable.
Onsubscribe). Call (subscriber);
Return Hook.onsubscribereturn (subscriber); catch (Throwable e) {//special handling for certain throwable/error/exception types exceptions
. Throwiffatal (e);
The subscriber can ' t listen to exceptions anymore if (subscriber.isunsubscribed ()) {
Rxjavapluginutils.handleexception (Hook.onsubscribeerror (e)); else {//IF An unhandled error occurs executing the onsubscribe we propagate it try {SUBSC
Riber.onerror (Hook.onsubscribeerror (e));
catch (throwable E2) {exceptions.throwiffatal (E2); If this is happens it means the OnError itself failed (perhaps an invalid function implementation)// So we are unable to propagate the error correctly and would just throw r = new RuntimeException Failedexception ("Error occurred attempting to subscribe [" + e.getmessage () + "] and then again while trying to
Error. ", E2);
TODO could the hook is the cause of the error in the "error handling."
Hook.onsubscribeerror (R);
TODO why aren ' t we throwing the hook ' s return value.
Throw R;
} return subscriptions.unsubscribed (); }
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26-27--28 29---30 31--32 33 34 35 36 37 38-39 40 41 42 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 1 2 3 4 5 6 7 8 9 10-11--12 13---14 15--16 17 18 19 20 21 22-23 24 25 26 8 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
Key code:
if (!) ( Subscriber instanceof Safesubscriber)) {
//Assign to ' observer ' so we return the protected version
Subscriber = n EW safesubscriber<t> (subscriber);
}
1 2 3 4 1 2 3 4
It will transfer our subscriber into the Safesubscriber,safesubcriber source code as follows:
public class Safesubscriber<t> extends subscriber<t> {private final subscriber< Super t> actual;
Boolean done = false;
Public Safesubscriber (SUBSCRIBER< Super t> Actual) {Super (Actual);
This.actual = actual;
}/** * Notifies the subscriber that {@code observable} has finished sending push-based.
* <p> * The {@code observable} would not be call this if it calls {@link #onError}.
*/@Override public void oncompleted () {if (!done) {done = true;
try {actual.oncompleted ();
The catch (Throwable e) {//We handle here instead of another method so we don ' t add stacks to the frame
which can prevent it from being able to handle StackOverflow (e);
Rxjavapluginutils.handleexception (e); throw new oncompletedfailedException (E.getmessage (), E); Finally {try {//similarly to OnError if failure occurs in unsubscribe then Rx con
Tract is broken//and we throw a unsubscribefailureexception.
Unsubscribe ();
catch (Throwable e) {rxjavapluginutils.handleexception (e);
throw new Unsubscribefailedexception (E.getmessage (), E); }}/** * Notifies the Subscriber that the {@code observable} has experienced a err
or condition. * <p> * If the {@code observable} calls this method, it won't thereafter call {@link #onNext} or * {@li
NK #onCompleted}. * * @param e * The exception encountered by the observable/@Override public void Onerr or (Throwable e) {//We handle here instead of another method so we don ' t add stacks to the frame//WHich can prevent it from being able to handle StackOverflow (e);
if (!done) {done = true;
_OnError (e);
}/** * Provides the subscriber with a new item to observe.
* <p> * The {@code observable} may call this is 0 or more times. * <p> * The {@code observable} would not call this