Quickly understand the design concept of Rxjava source code

Source: Internet
Author: User
Tags throwable

Objective

I have read a few about Rxjava source analysis of the blog, I do not know whether my level is limited or the source is too profound, resulting in a long time to figure out its operating principle. I personally think there should be a better way to quickly analyze the understanding, so decided to write this article.
This article is suitable has already seen some Rxjava source analysis material schoolmate, but did not see also does not matter. In this article can refer to this blog: Rxjava basic process and lift source code analysis, it said more complete, in this thank Bo Main head ghost Bruce.

First, a tentative study of Rxjava

"The following extracts the Rxjava basic process and lift source code Analysis"
Let's take a look at the most basic code and analyze how this code is implemented in Rxjava.

Observable.onsubscribe<string> OnSubscriber1 =NewObservable.onsubscribe<string> () {@Override     Public void Pager(SUBSCRIBER&LT;?Superstring> subscriber) {Subscriber.onnext ("1");    Subscriber.oncompleted (); }}; Subscriber<string> Subscriber1 =NewSubscriber<string> () {@Override     Public void oncompleted() {    }@Override     Public void OnError(Throwable e) {    }@Override     Public void OnNext(String s) {}};observable.create (onSubscriber1). Subscribe (SUBSCRIBER1);

First, let's take a look at the Observable.create code:

publicfinalstaticcreate(OnSubscribe<T> f) {    returnnew Observable<T>(hook.onCreate(f));}protectedObservable(OnSubscribe<T> f) {    this.onSubscribe = f;}

The observable constructor is called directly to create a new observable object, which we temporarily mark as observable1 so that it can be traced back.
At the same time, we will save our incoming Onsubscribe object OnSubscribe1 in the Onsubscribe attribute of Observable1, which is important in the context of the following.

Next, let's look at the subscribe method.

T> subscriber) {    return Observable.subscribe(subscriber, this);}private static <TT> subscriber, Observable<T> observable) {    ...    subscriber.onStart();    hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);    return hook.onSubscribeReturn(subscriber);}

As you can see, the Observable1.onSubscribe.call method is called directly after subscribe, which is the call method of the OnSubscribe1 object in our code.
, the passed-in parameter is the Subscriber1 object defined in our code. What you do in the call method is to invoke the OnNext and OnComplete methods of the incoming Subscriber1 object.
This enables the communication between the observer and the observed person.
"Excerpt Ends"
Well, here's a summary:

    • Processing data is the responsibility of the subscription class subscriber

To get started, let's look at the case with operators.

Second, the Rxjava application with operator

"The following extracts the Rxjava basic process and lift source code Analysis"
Show Demo First:

Observable.onsubscribe<string> OnSubscriber1 =NewObservable.onsubscribe<string> () {@Override     Public void Pager(SUBSCRIBER&LT;?Superstring> subscriber) {Subscriber.onnext ("1");    Subscriber.oncompleted (); }}; Subscriber<integer> Subscriber1 =NewSubscriber<integer> () {@Override     Public void oncompleted() {    }@Override     Public void OnError(Throwable e) {    }@Override     Public void OnNext(Integer i) {    }}; func1<string, integer> transformer1 =NewFunc1<string, integer> () {@Override     PublicIntegerPager(String s) {returnInteger.parseint (s); }};observable.create (onSubscriber1). Map (transformer1). Subscribe (SUBSCRIBER1);

Unlike just now, we called the map method after create and then called the Subscribe method.
"Excerpt Ends"
Then paste the Rxjava execution flow chart:

Let me start with this diagram to give the 3 guidelines that Rxjava can run:

    1. From the CREATE function can be executed down to subscribe, by returning the object of the observable class;
    2. From the Subscribe function can be executed up to OnSubscriber1, by the following observable object can invoke the above observable object Onsubscribe property;
    3. From the above can be again down to the data processing, relying on the subscriber responsibility chain.

Why don't I first analyze the source code and first give the guidelines? I found that if you do not know the criteria (or design ideas) to see the source code will be "see the tree not see the forest", and know the criteria to grasp the framework of the context, the rest of the source only to find the answer. Since this article has advertised the "Quick understanding Rxjava Source Design Idea", that certainly cannot illusory. Below we go to the source code to find the answer.

First, let's prove that guideline 1:

The code for the map method is as follows:

publicfinalmapsuper T, ? extends R> func) {    return lift(new OperatorMap<T, R>(func));}

The map returns the observable and proves it. Come on, it's so fast. The observable object returned by map is marked as observable2 here.

Re-certification Guideline 2:

Against the code in the demo, after we call map, we call the Subscribe method, which is called the subscribe method of the observable2 here.
As described above, after calling subscribe, the Observable2.onSubscribe.call method is called:

public   Final  <R> observable<r> lift  (final  operator<? Extends R,? super  T> operator) {return  new  observable<r > (new  onsubscribe<r> () { @Override  public  void   Call  (subscriber<?) super  R> o) {subscriber<? super             T> st = Hook.onlift (operator). Call (O);            St.onstart ();        Onsubscribe.call (ST); }    });}

The first sentence of the call function is related to the proof of guideline 3, which is not seen for the time being. The second sentence does not look (sorry, I did not understand this sentence to do, but does not affect the continuation of analysis), we look at the third sentence:

onSubscribe.call(st);

This is a key point, and the proof of guideline 2 depends on him. We need to figure out whose attributes Onsubscribe is. I'll write the demo in a different way:

...Observable.create(onSubscriber1);observable1.map(transformer1);observable2.subscribe(subscriber1);

The map function is Observable1, then the lift function is also observable1, according to Java syntax, the inner class can invoke the properties of the external class, so Onsubscribe is observable1. This achieves the goal that Observable2 crosses to Observable1. The certificate is completed.

Final Proof Guideline 3:

To tell you the truth, I feel that some of my classmates don't understand what's going on here. But it doesn't matter, I'll keep on telling.
Let's look at the Observable2.onSubscribe.call method:

public   Final  <R> observable<r> lift  (final  operator<? Extends R,? super  T> operator) {return  new  observable<r > (new  onsubscribe<r> () { @Override  public  void   Call  (subscriber<?) super  R> o) {subscriber<? super             T> st = Hook.onlift (operator). Call (O);            St.onstart ();        Onsubscribe.call (ST); }    });}

As mentioned earlier, the first sentence of the call function is related to the proof of guideline 3. Let's not see what it does, the return value gives St,st a Subscriber object. We conclude in the first section that processing data is the responsibility of the subscription class subscriber, so St has the responsibility to process the data. Then look at the third sentence, will St to the Observable1. The problem is, guideline 3 wants to run, it must have the subscriber responsibility chain. Where is the "chain"? Don't guess, I'll tell you the answer: "Chain" down the code in:

st = hook.onLift(operator).call(o);

Let's look at Operatormap's call method:

@Overridepublicsupercall(finalsuper R> o) {    returnnew Subscriber<T>(o) {        @Override        publicvoidonNext(T t) {            o.onNext(transformer.call(t));        }    };}

The entry parameter O is the Subscriber1 object in the demo. We look at it in this sentence:

o.onNext(transformer.call(t));

In accordance with the syntax, the parentheses are executed first. I write it more bluntly:

临时数据=map(处理前的数据);//本步骤处理subscriber1.onNext(临时数据);//提交给下一步处理

The code that goes up "chain" on:

onSubscribe.call(st);

To summarize:
Of the observers observable2 this operator returns, Onsubscribe will do two things:

    1. Build the subscription class subscriber in this level, connect this level of operations (map) with the next level of action in Subscriber (link down)
    2. Subscriber the generated subscription class in this level to the previous level observable, convenient up-level down link

Therefore, there are actually two responsibilities for this subscription class subscriber:

    1. Working with Data
    2. Connect to the next step subscriber
      A second picture helps digest:
PostScript: Rxjava Why do you do this?

I believe you are very impressed with the lift flowchart:

The first thing I saw was this: is it necessary to be so complicated? Fortunately, the decorator pattern and the chain of responsibility patterns in the design pattern can be understood in general. But the old question still exists: is it necessary to do so? The best way to learn a strange thing is to compare it with a familiar thing and think about what the software will do before it runs. The answer is configuration. In the Code

Observable.create(onSubscriber1)          .map(transformer1)          .subscribe(subscriber1);

Create or map, are all configured. Ask another question, how is the software configured to run? Either click the software or the command starts. Subscribe is the start. Well, we can do the abstraction. Whether it is Rxjava or software, its core is "Configuration + startup". What is the difference between Rxjava and software? You see the software is configured to start again, I have not seen the same as the "lift flowchart" the same as the string jump. This is Rxjava's design philosophy is different. I was thinking that if I were to design, I would first create a observable object, and then put the map type operator into an "Operation queue" in the observable object, so the configuration was done. When you need to start, call subscribe to start the "Action queue" process data, you see the code execution process is not very simple. This approach is achieved through the data structure, the advantage is that the source code execution process is clear and simple, the disadvantage is that this object too much responsibility. And Rxjava is through the chain of responsibility model reached, the advantage is the responsibility of decentralization, the disadvantage is that the source code to carry out a series of jumps. However, Rxjava in the design of the user has taken this into account, in fact, if you do not see the source code is only used Rxjava, for you, the execution is a line down is also very clear. OK, let's talk about it, hope to understand Rxjava can help.

Reference documents

Rxjava basic process and lift source code analysis
On the source of Rxjava

Quickly understand the design concept of Rxjava source code

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.