For more information, see RxJava (2: operators)
In the first blog, I introduced some basic knowledge about RxJava and the map () operator. Of course, if you don't want to use RxJava, I'm not surprised at all. After all, I got in touch with this point. After reading this blog, I believe you want to use RxJava immediately in your project. This blog will introduce many operators in RxJava. The strength of RxJava comes from the operators defined by RxJava.
First, let's look at an example:
Preparations assume that I have the following method:
This method returns the url list of a Website Based on the input string (AHA, search engine)
Observable
> query(String text);
Now I want to build a robust system that can query strings and display results. Based on the content of the previous blog, we may write the following code:
query(Hello, world!) .subscribe(urls -> { for (String url : urls) { System.out.println(url); } });
This type of code is of course intolerable, because the above Code makes us lose the ability to change data streams. Once we want to change every URL, we can only do it in Subscriber. We didn't use such a cool map () Operator !!!
Of course, I can use the map operator. The input of map is a urls list. It is also a pain point to traverse for each during processing.
Fortunately, there is also the Observable. from () method, which receives a set as input, and then outputs an element to subscriber each time:
Observable.from(url1, url2, url3) .subscribe(url -> System.out.println(url));
Let's use this method in the previous scenario:
query(Hello, world!) .subscribe(urls -> { Observable.from(urls) .subscribe(url -> System.out.println(url)); });
Although the for each loop is removed, the Code still looks messy. Multiple nested subparts not only look ugly, but are difficult to modify. What's more serious is that it will destroy some RxJava features that we haven't mentioned yet.
The improved savior is flatMap ().
Observable. flatMap () receives an Observable output as the input, and outputs Another Observable. View the Code directly:
query(Hello, world!) .flatMap(new Func1
, Observable
>() { @Override public Observable
call(List
urls) { return Observable.from(urls); } }) .subscribe(url -> System.out.println(url));
Here I posted the entire function code to help you understand what happened. Using lambda can greatly simplify the code length:
query(Hello, world!) .flatMap(urls -> Observable.from(urls)) .subscribe(url -> System.out.println(url));
Does flatMap () look strange? Why does it return another Observable? The key to understanding flatMap is that the new Observable output by flatMap is what we want to receive in Subscriber. Subscriber no longer receives List , But receives a single string of some columns, just like the output of Observable. from.
This is also the most difficult part for me to understand when I first learned RxJava. Once I suddenly understood it, many questions of RxJava will be solved together.
It can also be better. flatMap () cannot be better. It can return any Observable object it wants to return.
For example, the following method:
// Return the website title. If 404 is returned, nullObservable is returned.
GetTitle (String URL );
In the previous example, I don't want to print the URL, but I want to print the title of each website I received. The problem is that my method can only input one URL at a time, and the returned value is not a String, but an Observabl object that outputs a String. Using flatMap () can solve this problem easily.
query(Hello, world!) .flatMap(urls -> Observable.from(urls)) .flatMap(new Func1
>() { @Override public Observable
call(String url) { return getTitle(url); } }) .subscribe(title -> System.out.println(title));
Use lambda:
query(Hello, world!) .flatMap(urls -> Observable.from(urls)) .flatMap(url -> getTitle(url)) .subscribe(title -> System.out.println(title));
Isn't that incredible? I can combine multiple independent methods that return Observable objects! Handsome!
More than that, I also combined two API calls into a chain call. We can link any number of API calls. Everyone should know how painful it is to synchronize all API calls, and then combine the callback results of all API calls into the data to be displayed. Here we have successfully avoided callback hell (multi-layer nested callback, making it difficult to read and maintain the Code ). Now all the logic is encapsulated into this simple responsive call.
So far, we have come into contact with two operators. There are more operators in RxJava. How can we use other operators to improve our code?
GetTitle () returns null if the url does not exist. We do not want to output null, so we can filter out the null value from the returned title list!
query(Hello, world!) .flatMap(urls -> Observable.from(urls)) .flatMap(url -> getTitle(url)) .filter(title -> title != null) .subscribe(title -> System.out.println(title));
Filter () outputs the same elements as the input, and filters out those that do not meet the check conditions.
If we only want a maximum of five results:
query(Hello, world!) .flatMap(urls -> Observable.from(urls)) .flatMap(url -> getTitle(url)) .filter(title -> title != null) .take(5) .subscribe(title -> System.out.println(title));
Take () Outputs a maximum of a specified number of results.
If we want to save each title to the disk before printing:
query(Hello, world!) .flatMap(urls -> Observable.from(urls)) .flatMap(url -> getTitle(url)) .filter(title -> title != null) .take(5)www.bkjia.com .doOnNext(title -> saveTitle(title)) .subscribe(title -> System.out.println(title));
DoOnNext () allows us to do some additional things before each element is output, such as saving the title here.
Can you see how simple it is to operate data streams here. You can add any number of operations without messing up your code.
RxJava contains a large number of operators. The number of operators is a little scary, but it is worth looking at it, so that you can know which operators can be used. It may take some time to understand these operators, but once you understand them, you will have full control over the power of RxJava.
You can even write custom operators! This blog does not plan to use custom operators. If you want to use them, Google them on your own.
How do you feel? Well, you are a skeptical and hard to convince. Why do you care about these operators?
This is because operators allow you to perform any operations on data streams.
By linking a series of operators, you can complete complicated logic. Code is broken down into a series of clips that can be combined. This is the charm of responsive function programming. The more you use, the more you will change your programming thinking.
In addition, RxJava makes it easier to process data. In the last example, we call two APIs to process the data returned by the API and save it to the disk. But our Subscriber does not know this. It just thinks that it is receiving an Observable Object. Good encapsulation also facilitates coding!
In Part 3, I will introduce some other cool features of RxJava, such as error processing and concurrency, which are not directly used to process data.