Subject in Reactivex is as a bridge or proxy for observer and observerable. Because it is an observer, it can subscribe to one or more observable objects, and since he is an observable, it can pass and release the data objects it observes, and can release new objects.
1. Types of subject
There are four types of subject designed for different purposes, namely Asyncsubject, Behaviorsubject, Publishsubject and Replaysubject.
1.1 Asyncsubject
Asyncsubject only releases the last data released by observable, and only after observable is complete. However, if observable is terminated because of an exception, Asyncsubject will not release any data, but will pass an exception notification to observer.
1.2 Behaviorsubject
When observer subscribes to a behaviorsubject, it releases the recently released data object from the observable, which is a default value when no data is released. Next, all the data released by observable is released. If observable is terminated abnormally, Behaviorsubject will not release data to subsequent observer, but will pass an exception notification to observer.
1.3 Publishsubject
Publishsubject only releases data released after the subscription observable to observer.
1.4 Replaysubject
Regardless of when observer subscribes to Replaysubject,replaysubject, it releases observable freed data to all observer.
There are different types of replaysubject, which are used to limit the range of replay, such as setting the specific size of the buffer, or setting a specific time range.
If you use REPLAYSUBJECT as observer, be careful not to call the OnNext, OnComplete, and OnError methods in multiple threads, because this can lead to a sequence of confusion, which violates the observer rule.
2. Rxjava's subject source analysis2.1 Subject
Subject represents an object that is both observable and observer. The Code for class subject is as follows:
Package Rx.subjects;import Rx. Observable;import Rx. Observer;import Rx. subscriber;/** * Represents an object it is both a Observable and an Observer. * * Public Abstract class Subject<T, R> extends Observable<R > implements Observer<T> { protectedSubject (onsubscribe<r> onsubscribe) {Super(Onsubscribe); } Public Abstract BooleanHasobservers (); Public FinalSerializedsubject<t, r> toserialized () {return NewSerializedsubject<t, R> ( This); }}
2.2 Behaviorsubject
Subject has four primary subclasses, Asyncsubject, Behaviorsubject, Publishsubject, and Replaysubject, respectively. Next, we will take behaviorsubject as an example for source code analysis.
2.2.1 Behaviorsubject Subscription Subscribe process
When you need to use subject, call subject's subscribe (..) Method, the method actually calls the following subscribe (SUBSCRIBER<? Super T> Subscriber) method, so the other subscribe methods convert the input parameters into a Subscriber object.
Public final Subscription subscribe (subscriber<? superT> Subscriber) {...New Subscriber so onStart it Subscriber.onstart ();...The code below is exactly the same an unsafesubscribe and not used because it would add a sigificent depth to Alreay Hu GE call stacks.Try{//Allow the hook to intercept and/or decorate hook.onsubscribestart (this, onsubscribe). Call (SUBSC Riber);returnHook.onsubscribereturn (subscriber); } catch (Throwable e) {//Special handling forCertain throwable/error/exception types Exceptions.throwiffatal (e); //ifAn unhandled error occurs executing the onsubscribe we'll propagate itTry{Subscriber.onerror (Hook.onsubscribeerror (e)); } catch (onerrornotimplementedexception E2) {//special handling when onError are not implemented...We just rethrow throw E2; } catch (Throwable e2) {//ifThis happens it means the OnError itself failed (perhaps an invalidfunctionImplementation)//So we were unable to propagate the error correctly and would just throw Run Timeexception r = New RuntimeException ("Error occurred attempting to subscribe ["+ e.getmessage () +"] and then again while trying to pass to OnError.", E2); TODO could the hook be the cause of the errorinchThe On error handling. Hook.onsubscribeerror (R); TODO why aren' t we throwing the hook 'SreturnValue. Throw R; }returnSubscriptions.unsubscribed (); } }
Method Hook.onsubsribestart (this, onsubscribe). Call (subscriber) is equivalent to Onsubscribe.call (subscriber) by default. What is Onsubscriber? This requires an understanding of how the Behaviorsubject is constructed.
protectedBehaviorSubject(OnSubscribe<T> onSubscribe, SubjectSubscriptionManager<T> state) { super(onSubscribe); this.state = state;}
Where the constructor of the parent class subject is called
protectedSubject(OnSubscribe<R> onSubscribe) { super(onSubscribe);}
Where the constructor of the parent class observer is called
protectedObservable(OnSubscribe<T> f) { this.onSubscribe = f;}
Obsubscribe is the first parameter passed in the Behaviorsubject construction method.
Behaviorsubject has 3 static factory methods for producing Behaviorsubject objects.
Public Final class behaviorsubject<t> extends Subject<t, T> { Public Static<T> behaviorsubject<t> Create () {returnCreateNULL,false); } Public Static<T> behaviorsubject<t> Create (T defaultvalue) {returnCreate (DefaultValue,true); }Private Static<T> behaviorsubject<t> Create (T defaultvalue,BooleanHasDefault) {Finalsubjectsubscriptionmanager<t> State =NewSubjectsubscriptionmanager<t> ();if(HasDefault) {State.set (Notificationlite.instance (). Next (defaultvalue)); } state.onadded =NewAction1<subjectobserver<t>> () {@Override Public voidCall (Subjectobserver<t> o) {O.emitfirst (State.get (), state.nl); } }; state.onterminated = state.onadded;return NewBehaviorsubject<t> (State, state); } ....}
The static constructor method of the first two public actually calls the third private method.
The last return is new behaviorsubject<t> (state, state), so Onsubscribe is actually a Subjectsubscriptionmanager object, Onsubscribe.call (subscriber) actually calls the call method of Subjectsubscriptionmanager.
/ * Package * /Final class Subjectsubscriptionmanager<T> implements Onsubscribe <T> {... @Override Public voidCallFinalsubscriber<?SuperT> child) {subjectobserver<t> Bo =NewSubjectobserver<t> (child); Addunsubscriber (Child, Bo); Onstart.call (BO);if(!child.isunsubscribed ()) {if(Add (Bo) && child.isunsubscribed ()) {Remove (BO); } } }}
1. Call the Addunsubscriber method to register an action that executes when the subscription is canceled, removing the observer from the viewer.
/** Registers the unsubscribe action for the given subscriber. */voidsuperfinal SubjectObserver<T> bo) { child.add(Subscriptions.create(new Action0() { @Override publicvoidcall() { remove(bo); }
2. Call the Add (subjectobserver<t> O) method to add the observer to the registered observer[] array.
boolean add(SubjectObserver<T> o) { do { State oldState = state; if (oldState.terminated) { onTerminated.call(o); returnfalse; } State newState = oldState.add(o); if (STATE_UPDATER.compareAndSet(this, oldState, newState)) { onAdded.call(o); returntrue; } while (true);}
The method calls Onadd.call (O). Behaviorsubject's Onadd object is as follows, State.get () Gets the nearest data object, and O.emitfirst releases the nearest data object, which is a reflection of the Behaviorsubject feature.
new Action1<SubjectObserver<T>>() { @Override publicvoidcall(SubjectObserver<T> o) { o.emitFirst(state.get(), state.nl); }};
In this process, two internal classes of Subjectsubscriptionmanager are used.
1. state<t>
This class is used to manage the observer arrays that are already registered, as well as their state.
/** State-machine representing the termination state and active subjectobservers. * *protected StaticFinalclassstate<t> {Final Boolean terminated; Final subjectobserver[] observers;StaticFinal subjectobserver[] No_observers =Newsubjectobserver[0];StaticFinal state TERMINATED =NewState (true, no_observers);StaticFinal state EMPTY =NewState (false, no_observers); Public State(Boolean terminated, subjectobserver[] observers) { This. terminated = terminated; This. observers = observers; } PublicStateAdd(Subjectobserver o) { ... } PublicStateRemove(Subjectobserver o) { ... }}
2.subjectobserver<t>
This class when the observer of a decorative class, the use of decorative mode to the Observer class to add new features.
This is the process when the subject object subscribes to observer.
2.2.2 Behaviorsubject's OnNext
The Behavior OnNext (T V) method is as follows
@Overridepublic void onNext(T v) { laststate.get(); if (laststate.active) { Object n = nl.next(v); forstate.next(n)) { state.nl); } }}
State is the object of the Subjectsubscriptionmanager class, which is the object that maintains the recently freed data object, State.get () Gets the recently freed data object, State.next (object N) The Observer method re-sets the most recently freed data object and returns an array of already registered arrays.
SubjectObserver<T>[] next(Object n) { set(n); return state.observers;}
Bo.emitnext (object N, Final notificationlite<t> NL) Releases the given data object.
2.2.3 Behaviorsubject's oncompleted and onerror
OnCompleted and OnError call Subjectsubscriptionmanager's Terminate (object N) method, which will reset the recently freed data object and set the subject status to terminated , which indicates the end, and finally returns the registered observer array.
SubjectObserver<T>[] terminate(Object n) { set(n); false; State<T> oldState = state; if (oldState.terminated) { return State.NO_OBSERVERS; } return STATE_UPDATER.getAndSet(this, State.TERMINATED).observers;}
Copyright NOTICE: This article is the original blogger article, reprint please indicate the source http://blog.csdn.net/sun927
Rxjava Analysis-subject