The usage of Java Rxjava library operator and its example explanation _java

Source: Internet
Author: User

operator is to solve the problem of the transformation of the observable object, the operator is used to modify the observable event between the observable and the final subscriber. Rxjava provides many useful operators.
The map operator, for example, is used to convert an event to another event.

Observable.just ("Hello, world!") 
 . Map (new func1<string, string> () { 
   @Override public 
   string called (string s) {return 
     s + "-dan"; 
   } 
 }) 
 . Subscribe (s-> System.out.println (s)); 

Using a lambda can be simplified to

 
Observable.just ("Hello, world!") 
  . Map (s-> s + "-dan") 
  . Subscribe (S-> System.out.println (s)); 

Isn't it cool? The map () operator is used to transform the observable object, and the map operator returns a observable object so that a chained invocation can be implemented that uses the map operator multiple times on a observable object. Finally, the most concise data is passed to the Subscriber object.


Map Operations Fu Jinjie
the more interesting point of the map operator is that it does not have to return the type returned by the observable object, and you can use the map operator to return a observable object that emits a new data type.
For example, in the above example, subscriber doesn't care about the returned string, but the hash value of the string.

Observable.just ("Hello, world!") 
  . Map (new func1<string, integer> () { 
    @Override public 
    Integer Call (String s) {return 
      s.hashcode (); 
    } 
  }) 
  . Subscribe (i-> System.out.println (integer.tostring (i))); 

Isn't it funny? Our initial observable returns a string, and the final subscriber receives an integer, of course, using a lambda can further simplify the code:

Observable.just ("Hello, world!") 
  . Map (S-> s.hashcode ()) 
  . Subscribe (i-> System.out.println (integer.tostring (i))); 

As I said before, the fewer things subscriber do, the better, we add a map operator

Observable.just ("Hello, world!") 
  . Map (S-> s.hashcode ()) 
  . Map (i-> integer.tostring (i)) 
  . Subscribe (S-> System.out.println (s)); 

Refuses
Do you think our example is too simple to convince you? You need to understand the following two points:
1.Observable and subscriber can do anything.
Observable can be a database query, Subscriber used to display query results, observable can be on-screen click events, subscriber to respond to click events, observable can be a network request, Subscriber is used to display the request results.
2.Observable and Subscriber are independent of the intermediate transformation process.
Any number of maps can be added or subtracted between observable and subscriber. The whole system is highly configurable, and manipulating the data is a very simple process.

Instance
1. Preparatory work
Suppose I have such a method:
This method returns a list of URLs for a Web site based on the input string (AHA, search engine)

observable<list<string>> query (String text);  

Now I want to build a robust system that can query strings and display the results. Based on the contents of the previous blog, we might write the following code:

Query ("Hello, world!") 
  . Subscribe (URLs-> {for 
    (String url:urls) { 
      System.out.println (URL); 
    } 
  }); 

This kind of code, of course, is intolerable, because the above code deprives us of the ability to change the flow of data. Once we want to change each URL, we can only do it in the Subscriber. We didn't use such a cool map () operator!!!

Of course, I can use the map operator, the input of map is the list of URLs, the processing time or for each traversal, as very egg pain.

Luckily, there is also the Observable.from () method that receives a collection as input and then outputs one element at a time to Subscriber:

Observable.from ("Url1", "Url2", "Url3") 
  . Subscribe (URL-> System.out.println (URL)); 

Let's use this approach to the scene just now:

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 subscription not only look ugly, they are difficult to modify, but more serious is that it destroys some of the Rxjava features that we have not yet talked about.

2. Improved
The Savior is coming, he is flatmap ().
Observable.flatmap () receives a observable output as input, while outputting another observable. Look directly at the code:

Query ("Hello, world!") 
  . Flatmap (new Func1<list<string>, observable<string>> () { 
    @Override public 
    observable< string> call (list<string> URL) {return 
      observable.from (URLs); 
    } 
  }) 
  . Subscribe (URL-> System.out.println (URL)); 

Here I post the entire function code to make it easy for you to understand what's going on, and using a lambda can greatly simplify the length of the code:

 Query ("Hello, world!") 
  . Flatmap (URLs-> observable.from (URLs)) 
  . Subscribe (URL-> System.out.println (URL)); 

Does Flatmap () look strange? Why does it return to another observable? The key point of understanding Flatmap is that the flatmap output of the new observable is exactly what we want to receive in subscriber. Now subscriber no longer receive LIST<STRING>, but rather receives a string of individual columns, just like the output of Observable.from ().

This part is also when I learned rxjava the most difficult to understand the part, once I suddenly understand, rxjava a lot of questions will be solved.

3. can also be better
Flatmap () can't be more awesome, it can return any observable object it wants to return.
For example, the following method:

Returns the title of the Web site, and returns a null 
observable<string> getTitle (String URL) if 404 is returned; 


Then, for the previous example, I don't want to print the URL anymore, but I want to print the title of each site I receive. The problem is, my method can only pass in one URL at a time, and the return value is not a string, but rather a observabl object that outputs a string. Using Flatmap () can be a simple solution to this problem.

Query ("Hello, world!") 
  . Flatmap (URLs-> observable.from (URLs)) 
  . Flatmap (New func1<string, observable<string>> () { 
    @ Override public 
    observable<string> call (String URL) {return 
      getTitle (URL); 
    } 
  }) 
  . Subscribe (title-> System.out.println (title)); 

4. Use lambda:

Query ("Hello, world!") 
  . Flatmap (URLs-> observable.from (URLs)) 
  . Flatmap (url-> getTitle (URL)) 
  . Subscribe (Title-> System.out.println (title)); 

Does it feel so weird? I was able to combine multiple independent methods of returning observable objects! It's awesome!
More than that, I've also combined the calls of two APIs into a chained invocation. We can link any number of API calls. You should all be aware that synchronizing all API calls and then combining all the callback results of all API calls into the data that needs to be displayed is an egg ache. Here we have successfully avoided callback Hell (multiple nested callbacks, resulting in code that is difficult to read and maintain). Now all the logic is packaged into this simple response call.

5. A rich operator
So far, we've contacted two operators, and there are more operators in Rxjava, so how do we use other operators to improve our code?
GetTitle () returns null if the URL does not exist. We don't 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)); 

The filter () outputs and inputs the same elements, and filters out those that do not satisfy the check condition.

If we only want a maximum of 5 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 specified number of results.

If we want to save each title to disk before printing:

Query ("Hello, world!") 
  . Flatmap (URLs-> observable.from (URLs)) 
  . Flatmap (url-> getTitle (URL)) 
  . Filter (title-> title!= null ) 
  . Take (5). 
  Doonnext (title-> savetitle (title) 
  . Subscribe (title-> System.out.println (title) ); 

Doonnext () allows us to do something extra before outputting one element at a time, such as the save title here.

See how easy it is to manipulate the data stream here. You can add as many actions as you want without messing up your code.

Rxjava contains a number of operators. The number of operators is a bit scary, but it's worth looking at each one, so you can see which operators are available. It may take some time to understand these operators, but once you understand them, you have a complete grasp of the power of Rxjava.

You can even write custom operators! This blog does not intend to customize the operator, if you want to, clear yourself Google it.

How do you feel?
Well, you're a skeptic, and it's hard to be persuaded, so why do you care about these operators?

Because the operator allows you to do anything with the data stream.

Complex logic can be accomplished by connecting a series of operations linked. The code is decomposed into a series of fragments that can be combined. This is the appeal of response-style functional programming. The more you use, the more you will change your programming thinking.

In addition, Rxjava also makes it easier for us to process data. In the last example, we called two APIs, processed the data returned by the API, and then saved it to disk. But our subscriber don't know that, it just thinks they're receiving a observable<string> object. Good encapsulation also brings the convenience of coding!


In the third part, I'll introduce some of the other cool features of Rxjava, such as error handling and concurrency, that aren't directly used to process data.

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.