RxJava development essentials 6-combination of Observables

Source: Internet
Author: User

RxJava development essentials 6-combination of Observables

In the previous chapter, we learned how to convert observability sequences. We also sawmap(),scan(),groupBY()And more examples of useful functions. They help us operate the Observable to create the Observable we want.

In this chapter, we will study combined functions and learn how to process multiple Observables at the same time to create the desired Observable.

Merge

This scenario is often created in an asynchronous world. We have multiple sources but only want to have one result: multiple inputs and single outputs. RxJavamerge()The method will help you merge two or more Observables into the data they are launching. The combination of the two sequences in a final transmitted Observable is given.

As you can see, the transmitted data is merged into an Observable. Note that if you synchronize the merged Observable, they will be connected together and will not cross. <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4NCjxwPs/issue + uq/K/c/xz8ld5txi0fmjuw.vcd4ncjxwcmugy2xhc3m9 "brush: java;"> private void loadList(List apps) { mRecyclerView.setVisibility(View.VISIBLE); List reversedApps = Lists.reverse(apps); Observable observableApps =Observable.from(apps); Observable observableReversedApps =Observable.from(reversedApps); Observable mergedObserbable = Observable.merge(observableApps,observableReversedApps); mergedObserbable.subscribe(new Observer(){ @Override public void onCompleted() { mSwipeRefreshLayout.setRefreshing(false); Toast.makeText(getActivity(), "Here is the list!", Toast.LENGTH_LONG).show(); } @Override public void onError(Throwable e) { Toast.makeText(getActivity(), "One of the two Observable threw an error!", Toast.LENGTH_SHORT).show(); mSwipeRefreshLayout.setRefreshing(false); } @Override public void onNext(AppInfoappInfo) { mAddedApps.add(appInfo); mAdapter.addApplication(mAddedApps.size() - 1, appInfo); } });}

We have created the Observable and observableApps data and the new observableReversedApps reverse list. UseObservable.merge(), We can create a newObservableMergedObservableAll data sent from the source Observables in a single observability sequence.

As you can see, every method signature is the same, so our observers can reuse code without worrying about any difference. The result is as follows:

Note the toast message when an error occurs. You can think that the error thrown by each Observable will interrupt the merge. RxJava providesmergeDelayError()It can continue to transmit data from an Observable, even if one of them throws an error. When all the Observables are completed,mergeDelayError()Will launchonError(), As shown in:

ZIP

When processing multiple sources, we may bring about such a scenario: receiving data from multiple Observables, processing them, and then merging them into a new observability sequence. RxJava has a special method to accomplish this:zip()Merges two or more data items emitted by the Observables according to the specified function.Func*Convert them and emit a new value. Shownzip()How to deal with the released "numbers" and "letters" and then merge them into a new data item:

For the "real world" example, we will use the installed Application List and a new dynamic Observable to make the example a bit interesting.

Observable
  
    tictoc = Observable.interval(1, TimeUnit.SECONDS);
  

tictocObservable variable usageinterval()The function generates a Long data type per second: simple and efficient. As we mentioned earlier, we needFuncObject. Because it requires two parametersFunc2:

private AppInfo updateTitle(AppInfoappInfo, Long time) {    appInfo.setName(time + " " + appInfo.getName());    return appInfo;}

Now ourloadList()The function becomes like this:

private void loadList(List
  
    apps) {    mRecyclerView.setVisibility(View.VISIBLE);    Observable observableApp = Observable.from(apps);    Observable
   
     tictoc = Observable.interval(1, TimeUnit.SECONDS);    Observable.zip(observableApp, tictoc,    (AppInfo appInfo, Long time) -> updateTitle(appInfo, time))    .observeOn(AndroidSchedulers.mainThread())    .subscribe(new Observer() {        @Override        public void onCompleted() {            Toast.makeText(getActivity(), "Here is the list!", Toast.LENGTH_LONG).show();        }        @Override        public void onError(Throwable e) {            mSwipeRefreshLayout.setRefreshing(false);            Toast.makeText(getActivity(), "Something went wrong!", Toast.LENGTH_SHORT).show();        }        @Override        public void onNext(AppInfoappInfo) {            if (mSwipeRefreshLayout.isRefreshing()) {                mSwipeRefreshLayout.setRefreshing(false);            }             mAddedApps.add(appInfo);            int position = mAddedApps.size() - 1;            mAdapter.addApplication(position, appInfo);            mRecyclerView.smoothScrollToPosition(position);        }    });}
   
  

As you can see,zip()The function has three parameters: Two Observables and oneFunc2.

A closer look will show youobserveOn()Function. It will be explained in the next chapter: now we can try it out.

The result is as follows:

Join

The first two methods,zip()Andmerge()Methods are used in the scope of data transmission. We need to consider time in some scenarios before deciding how to operate values. RxJavajoin()The function combines the data transmitted by two Observables based on the time window.

For a correct understanding of the previous figure, we will explainjoin()Required parameters:

The second Observable is combined with the source Observable. Func1Parameter: during the specified time interval defined by the time window, the data transmitted by the source Observable and the data transmitted from the second Observable work together to return the Observable. Func1Parameter: within the specified time interval defined by the time window, the data transmitted by the second Observable matches the data transmitted from the source Observable to the returned Observable. Func2Parameter: defines how the transmitted data is combined with the newly released data item.
For example, we can modify loadList()Functions are as follows:
private void loadList(List
  
   
     apps) {    mRecyclerView.setVisibility(View.VISIBLE);    Observable appsSequence =    Observable.interval(1000, TimeUnit.MILLISECONDS)                .map(position -> {                    return apps.get(position.intValue());                });    Observable
    
      tictoc = Observable.interval(1000,TimeUnit.MILLISECONDS);    appsSequence.join(        tictoc,         appInfo -> Observable.timer(2,TimeUnit.SECONDS),        time -> Observable.timer(0, TimeUnit.SECONDS),        this::updateTitle)        .observeOn(AndroidSchedulers.mainThread())        .take(10)        .subscribe(new Observer() {            @Override            public void onCompleted() {                Toast.makeText(getActivity(), "Here is the list!", Toast.LENGTH_LONG).show();            }            @Override            public void onError(Throwable e) {                mSwipeRefreshLayout.setRefreshing(false);                 Toast.makeText(getActivity(), "Something went wrong!", Toast.LENGTH_SHORT).show();            }            @Override            public void onNext(AppInfoappInfo) {                if (mSwipeRefreshLayout.isRefreshing()) {                    mSwipeRefreshLayout.setRefreshing(false);                }                 mAddedApps.add(appInfo);                int position = mAddedApps.size() - 1;                mAdapter.addApplication(position, appInfo);                mRecyclerView.smoothScrollToPosition(position);            }         });}
    
   
  

We have a new object.appsSequenceIt is an observability sequence that transmits app data from the list of installed apps per second.tictocThis Observable data only emits one newLongType integer. To merge them, we need to specify twoFunc1Variable:

appInfo -> Observable.timer(2, TimeUnit.SECONDS)time -> Observable.timer(0, TimeUnit.SECONDS)

Two time windows are described above. The following line describes how to useFunc2Combine the two launch data.

this::updateTitle

The result is as follows:

It looks messy, but pay attention to the app name and the specified time window. We can see that once the second data is released, it will be combined with the source data, however, we use the same source data for 2 seconds. This is why repeated titles are accumulated.

It is worth mentioning that for the sake of simplicity, there is alsojoin()The operator acts on the string and then simply connects to the transmitted string to form the final string.

CombineLatest

RxJavacombineLatest()Functions look a bit likezip()Special form of a function. As we have learned,zip()It acts on two unpackaged Observables. On the contrary,combineLatest()Act on recently released data items: IfObservable1Launch A andObservable2Launched B and C,combineLatest()AB and AC will be grouped, as shown in:

combineLatest()The function accepts two to nine Observable values as parameters, or a single Observables list as parameters if necessary.

In the previous exampleloadList()If the function is borrowed, We can modify itcombineLatest()The following example shows how to implement "real world:

private void loadList(List
  
   
    
      apps) {    mRecyclerView.setVisibility(View.VISIBLE);    Observable appsSequence = Observable.interval(1000, TimeUnit.MILLISECONDS)              .map(position ->apps.get(position.intValue()));    Observable
     
       tictoc = Observable.interval(1500, TimeUnit.MILLISECONDS);    Observable.combineLatest(appsSequence, tictoc,               this::updateTitle)       .observeOn(AndroidSchedulers.mainThread())        .subscribe(new Observer() {        @Override        public void onCompleted() {            Toast.makeText(getActivity(), "Here is the list!", Toast.LENGTH_LONG).show();        }        @Override        public void onError(Throwable e) {            mSwipeRefreshLayout.setRefreshing(false);            Toast.makeText(getActivity(), "Something went wrong!", Toast.LENGTH_SHORT).show();        }        @Override        public void onNext(AppInfoappInfo) {            if (mSwipeRefreshLayout.isRefreshing()) {                mSwipeRefreshLayout.setRefreshing(false);            }             mAddedApps.add(appInfo);            int position = mAddedApps.size() - 1;            mAdapter.addApplication(position, appInfo);            mRecyclerView.smoothScrollToPosition(position);        }     });}
     
    
   
  

We use two Observables: one is to transmit an App data from the list of installed apps every second, and the other is to launch an App data every 1.5 seconds.LongType integer. We combine them and executeupdateTitle()Function. The result is as follows:

As you can see, due to different time intervals,AppInfoObjects are repeated as we expected.

And, Then And When

There will be morezip()Scenarios that cannot be met. For example, you can use And/Then/When solutions for complex architectures or just for personal interests. Under RxJava's joins package, they use Pattern and Plan as the intermediary to merge the transmitted data sets together.

OurloadList()The function will be modified from the following:

private void loadList(List
  
   
    
     
       apps) {    mRecyclerView.setVisibility(View.VISIBLE);    Observable observableApp = Observable.from(apps);    Observable
      
        tictoc = Observable.interval(1, TimeUnit.SECONDS); Pattern2 pattern = JoinObservable.from(observableApp).and(tictoc); Plan0 plan = pattern.then(this::updateTitle); JoinObservable .when(plan) .toObservable() .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer() { @Override public void onCompleted() { Toast.makeText(getActivity(), "Here is the list!", Toast.LENGTH_LONG).show(); } @Override public void onError(Throwable e) { mSwipeRefreshLayout.setRefreshing(false); Toast.makeText(getActivity(), "Something went wrong!", Toast.LENGTH_SHORT).show(); } @Override public void onNext(AppInfoappInfo) { if (mSwipeRefreshLayout.isRefreshing()) { mSwipeRefreshLayout.setRefreshing(false); } mAddedApps.add(appInfo); int position = mAddedApps.size() - 1; mAdapter.addApplication(position, appInfo); mRecyclerView.smoothScrollToPosition(position); } });}
      
     
    
   
  

Like in general, we have two emission sequences,observableAppTo launch the list of installed applications,tictocOne per secondLongType integer. Now we useand()Connect the source Observable and the second Observable.

JoinObservable.from(observableApp).and(tictoc);

CreatepatternObject. With this object, we can createPlanObject: "We have two Observables for transmitting data,then()What is it ?"

pattern.then(this::updateTitle);

Now we havePlanAnd when the plan happens, we can decide what will happen next.

.when(plan).toObservable()

At this time, we can subscribe to the new Observable, as we always do.

Switch

In such a complex scenariosubscribe-unsubscribeIn the sequence, we can automatically unsubscribe from an Observable to subscribe to a new Observable.

RxJavaswitch(), As defined, convert one Observable that emits multiple Observables into another independent Observable, which then emits the data items that have been recently released by the Observables.

A source Observable that transmits multiple Observables sequences is provided,switch()Subscribe to the source Observable and start to transmit the same data from the first transmitted Observable. When the source Observable emits a new Observable,switch()Immediately unsubscribe to the previous transmitted data's Observable (which interrupts the data stream from it), subscribe to a new Observable, and start to launch its data.

StartWith

We have learned how to connect multiple Observables and append the specified values to an emission sequence. RxJavastartWith()Yesconcat(). Asconcat()Append data to the Observable of the data to be sent. Before the Observable starts to transmit their data,startWith()Transmit a data sequence by passing a parameter.

Summary

In this chapter, we learned how to combine two or more Observable to create a new observability sequence. We will be ablemergeObservable,joinObservables,zipAnd combine them in several situations!

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.