RxJava as I understand it - it's actually very easy to get started (2)

RxJava as I understand it - it's actually very simple to get started (2)

144 
  AuthorWeavey _  
2016.08.31 17:05*   Word count 2512   Read 11324 Comments 27

foreword

Welcome to continue to watch "RxJava as I understand it--it's easy to get started (2)", the first article was published last week, and the response from all the programmers was not bad. The first blog post in my life can be affirmed by everyone, and my heart is affirmed. I am very happy, and it also strengthened my belief in continuing to write. In short, thank you all for the fish balls... oh no, it's a collection. Okay, I won’t say much more off topic. Entering the topic of this article, this article mainly supplements the Subjectknowledge left over from the previous article. Students who haven’t read the previous article, students who forgot what I wrote in the previous chapter, and others Other students, please enter the time machine: RxJava as I understand it - it is actually very simple to get started (1) Review it once, as the saying goes, "read a book a hundred times, and see it for yourself." After reviewing, please come back to continue listening.


About Subject

Regarding Subject, the official documentation explains this: Subject can be seen as a bridge or proxy, and in some ReactiveX implementations (such as RxJava), it acts as both Observer and Observable. Because it is an Observer, it can subscribe to one or more Observables; and because it is an Observable, it can forward the data it receives (Observe), and it can also emit new data. From the official explanation, I extracted three main points:

  1. It can act as an Observable;
  2. It can act as an Observer;
  3. It is a bridge between Observable and Observer;

Next, I will explain these three points, but before explaining, we must first introduce the type of Subject. Subject is an abstract class and cannot be instantiated through new, so Subject has four implementation classes, namely AsyncSubject and BehaviorSubject , PublishSubject and ReplaySubject , each implementation class has specific "skills", the following combined with the code to introduce their respective "skills". Note that all implementation classes are create()instantiated by methods, without new, all implementation classes call onCompleted()or onError(), its Observer will no longer receive data;


Classification Analysis of Subject

  • The AsyncSubject
    Observer will receive `onComplete()the last data of the AsyncSubject. If it terminates due to an exception, the AsyncSubject will not release any data, but will deliver an exception notification to the Observer. The sample code is as follows:

          AsyncSubject<String> asyncSubject = AsyncSubject.create();
          asyncSubject.onNext("asyncSubject1");
          asyncSubject.onNext("asyncSubject2");
          asyncSubject.onNext("asyncSubject3");  
          asyncSubject.onCompleted();
          asyncSubject.subscribe(new Observer<String>() {
              @Override
              public void onCompleted() {
    
                  LogUtil.log("asyncSubject onCompleted");  //输出 asyncSubject onCompleted
              }
    
              @Override
              public void onError(Throwable e) {
    
                  LogUtil.log("asyncSubject onError");  //不输出(异常才会输出)
              }
    
              @Override
              public void onNext(String s) {
    
                  LogUtil.log("asyncSubject:"+s);  //输出asyncSubject:asyncSubject3
              }
          });

    In the above code, Observer will only receive the last data before onCompleted() of asyncSubject is called, namely "asyncSubject3". If onCompleted() is not called, Subscriber will not receive any data.

  • BehaviorSubject
    Observer会接收到BehaviorSubject被订阅之前的最后一个数据,再接收其他发射过来的数据,如果BehaviorSubject被订阅之前没有发送任何数据,则会发送一个默认数据。(注意跟AsyncSubject的区别,AsyncSubject要手动调用onCompleted(),且它的Observer会接收到onCompleted()前发送的最后一个数据,之后不会再接收数据,而BehaviorSubject不需手动调用onCompleted(),它的Observer接收的是BehaviorSubject被订阅前发送的最后一个数据,两个的分界点不一样,且之后还会继续接收数据。)示例代码如下:

      BehaviorSubject<String> behaviorSubject = BehaviorSubject.create("default");
      behaviorSubject.onNext("behaviorSubject1");
      behaviorSubject.onNext("behaviorSubject2");
          behaviorSubject.subscribe(new Observer<String>() {
              @Override
              public void onCompleted() {
    
                  LogUtil.log("behaviorSubject:complete");
              }
    
              @Override
              public void onError(Throwable e) {
    
                  LogUtil.log("behaviorSubject:error");
              }
    
              @Override
              public void onNext(String s) {
    
                  LogUtil.log("behaviorSubject:"+s);
              }
          });
    
          behaviorSubject.onNext("behaviorSubject3");
          behaviorSubject.onNext("behaviorSubject4");

    以上代码,Observer会接收到behaviorSubject2、behaviorSubject3、behaviorSubject4,如果在behaviorSubject.subscribe()之前不发送behaviorSubject1、behaviorSubject2,则Observer会先接收到default,再接收behaviorSubject3、behaviorSubject4。

  • PublishSubject
    PublishSubject比较容易理解,相对比其他Subject常用,它的Observer只会接收到PublishSubject被订阅之后发送的数据。示例代码如下:

      PublishSubject<String> publishSubject = PublishSubject.create();
      publishSubject.onNext("publishSubject1");
      publishSubject.onNext("publishSubject2");
      publishSubject.subscribe(new Observer<String>() {
              @Override
              public void onCompleted() {
    
              }
    
              @Override
              public void onError(Throwable e) {
    
              }
    
              @Override
              public void onNext(String s) {
                  LogUtil.log("publishSubject observer1:"+s);
              }
          });
      publishSubject.onNext("publishSubject3");
      publishSubject.onNext("publishSubject4");

    以上代码,Observer只会接收到"behaviorSubject3"、"behaviorSubject4"。

  • ReplaySubject
    ReplaySubject会发射所有数据给观察者,无论它们是何时订阅的。也有其它版本的ReplaySubject,在重放缓存增长到一定大小的时候或过了一段时间后会丢弃旧的数据。示例代码如下:
    ReplaySubject<String>replaySubject = ReplaySubject.create(); //创建默认初始缓存容量大小为16的ReplaySubject,当数据条目超过16会重新分配内存空间,使用这种方式,不论ReplaySubject何时被订阅,Observer都能接收到数据
    //replaySubject = ReplaySubject.create(100);//创建指定初始缓存容量大小为100的ReplaySubject
    //replaySubject = ReplaySubject.createWithSize(2);//只缓存订阅前最后发送的2条数据 
    //replaySubject=ReplaySubject.createWithTime(1,TimeUnit.SECONDS,Schedulers.computation());  //replaySubject被订阅前的前1秒内发送的数据才能被接收     
    replaySubject.onNext("replaySubject:pre1");
    replaySubject.onNext("replaySubject:pre2");
    replaySubject.onNext("replaySubject:pre3");
    replaySubject.subscribe(new Action1<String>() {
          @Override
          public void call(String s) {
                  LogUtil.log("replaySubject:" + s);
          }
      });
    replaySubject.onNext("replaySubject:after1");
    replaySubject.onNext("replaySubject:after2");
    以上代码,由于情况比较多,注释也已解释的相当清楚,就不对输出结果一一表述了,有疑问的自行copy代码去测试一下。至此,四种Subject类型已经介绍完毕,但是需要注意,如果你把 Subject 当作一个 Subscriber 使用,不要从多个线程中调用它的onNext方法(包括其它的on系列方法),这可能导致同时(非顺序)调用,这会违反Observable协议,给Subject的结果增加了不确定性。要避免此类问题,官方提出了“串行化”,你可以将 Subject 转换为一个 SerializedSubject ,类似于这样:
    SerializedSubject<String, Integer> ser = new SerializedSubject(publishSubject);

要点解答

接下来,我们继续前面提出的问题,为什么说Subject既可充当Observable,又可充当Observer,是它们两个之间的桥梁呢?经过前面的例子,也许有些人已经大概理解了,不理解的且听我细细道来。首先,从理论上讲,Subject继承了Observable,又实现了Observer接口,所以说它既是Observable又是Observer,完全合理。从实际应用上讲,Subject也能实现Observable和Observer相同的功能,口说无凭,我们还是通过代码来证实比较有说服力。

  • 创建Observable并发射数据:

      Observable.create(new Observable.OnSubscribe<String>() {
              @Override
              public void call(Subscriber<? super String> subscriber) {
    
                  subscriber.onNext("I'm Observable");
                  subscriber.onCompleted();
              }
          });

    用Subject实现为:

    PublishSubject<String> publishSubject = PublishSubject.create();
    publishSubject.onNext("as Observable");
    publishSubject.onCompleted();
  • 创建Observer订阅Observable并接收数据:

    mObservable.subscribe(new Observer<String>() {
          @Override
           public void onCompleted() {
    
          }
    
          @Override
          public void onError(Throwable e) {
    
          }
    
          @Override
          public void onNext(String s) {
    
                  //接收数据
          }
    });

    用Subject实现为:

       publishSubject.subscribe(new Observer<String>() {
              @Override
              public void onCompleted() {
    
              }
    
              @Override
              public void onError(Throwable e) {
    
              }
    
              @Override
              public void onNext(String s) {
    
              }
          });

    也许有人会问,不是说Subject也可以作为Observer,不能把Subject当作Observer传入subscribe()中吗?回答是:当然可以!就象这样:

    PublishSubject<String> publishSubject = PublishSubject.create();
    Observable.create(new Observable.OnSubscribe<String>() {
          @Override
          public void call(Subscriber<? super String> subscriber) {
    
              subscriber.onNext("as Observer"); 
              subscriber.onCompleted();
          }
    }).subscribe(publishSubject);

    Did you find a problem? publishSubject does not have an overriding onNext()method, where is the received data? This is the problem of the "bridge" mentioned above. Although the Subject is passed in as the Observer subscribe(), the received data must be received through the Observer, and the Subject is used to connect the Observable and the Observer. The overall code is as follows:

    PublishSubject<String> publishSubject = PublishSubject.create();
       Observable.create(new Observable.OnSubscribe<String>() {
              @Override
              public void call(Subscriber<? super String> subscriber) {
    
                  subscriber.onNext("as Bridge");
                  subscriber.onCompleted();
              }
          }).subscribe(publishSubject);
    
          publishSubject.subscribe(new Observer<String>() {
              @Override
              public void onCompleted() {
    
              }
    
              @Override
              public void onError(Throwable e) {
    
              }
    
              @Override
              public void onNext(String s) {
    
                  LogUtil.log("subject:"+s); //接收到 as Bridge
              }
          });

    That's right, it's a bridge!


Summarize

About Subject, this is the end of the introduction. Maybe you will be as confused as me, why multiple Subjects come out, except for a few specific functions, everything else, Observable and Observer also have, and the writing method is not as simple as the original. Indeed, for a few specific functions, I still can't think of any application scenarios, at least I haven't found any scenarios that must be implemented with Subject, then the question comes again, why do I spend so much time introducing Subject , for three reasons. First, since the official launch of Subject, there must be a reason. If you haven’t encountered it yet, it doesn’t mean you won’t encounter it in the future, and it doesn’t mean you won’t encounter such an application scenario. Second, “There are a thousand readers in a thousand. Hamlet", that's not all I see, maybe you'll find something more interesting? Third, I don’t want you to read all my articles about RxJava and be confident that you have already started RxJava. When someone mentions Subject to you, you are at a loss and don’t know what a Subject is. Isn’t it sad? Therefore, it is very meaningful to introduce the subject. At least learning it is better than not learning it at all. "Raising a soldier for a thousand days and using a soldier for a while" is not too much knowledge, but suddenly it is used one day. For Subject's understanding, those who have objections are welcome to comment below and communicate progress together. In the next article, enter the explanation of the use of RxJava operators.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325522955&siteId=291194637