Rxjava's GitHub homepage, the deployment part has nothing to say ~
Https://github.com/ReactiveX/RxJava
Basis
The two core Rxjava are observables (observed, event source) and Subscribers (Observer). Observables emits a series of events subscribers handle these events. The event here can be anything you are interested in (touch events, web interface calls return data ...). )
A observable can emit 0 or more events, knowing the end or error. Each event is emitted, its subscriber OnNext method is invoked, and the last Call to Subscriber.onnext () or Subscriber.onerror () ends.
Rxjava looks like the observer pattern in the design pattern, but there is one obvious difference, that is, if a observerble does not have any subscriber, then this observable does not emit any events.
Hello World
creating a Observable object is simple, calling Observable.create directly
observable<string> myobservable = observable.create (
new observable.onsubscribe<string> () {
@ Override public
void Call (subscriber<. Super String> Sub) {
sub.onnext ("Hello, world!");
Sub.oncompleted ();
}
);
The observable object defined here simply emits a Hello world string, and then it ends. We then create a subscriber to handle the string emitted by the observable object.
subscriber<string> mysubscriber = new subscriber<string> () {
@Override public
void OnNext (String s ) {System.out.println (s);}
@Override public
void oncompleted () {}
@Override public
void OnError (Throwable e) {}
};
Here subscriber just print the observable out of the string. By using the Subscribe function, we can associate the Myobservable object we defined with the Mysubscriber object, thus completing the Subscriber subscription to observable.
Myobservable.subscribe (Mysubscriber);
Once Mysubscriber subscribe to myobservable,myobservable is to invoke the OnNext and OnComplete method of the Mysubscriber object, Mysubscriber will print the Hello world!
More Concise Code
do you think it's too verbose to write so much code just to print a Hello world? I am here mainly to show the principle behind the Rxjava and use this more verbose writing, Rxjava actually provides a lot of convenient functions to help us reduce the code.
First let's look at how to simplify the creation of observable objects. Rxjava has a number of built-in functions for simplifying the creation of observable objects, such as Observable.just, which is used to create observable objects that simply emit an event, and the code that creates the observable object can be simplified to one line
observable<string> myobservable = Observable.just ("Hello, world!");
Let's take a look at how to simplify subscriber, in the example above, we don't really care about oncomplete and onerror, we just need to do some processing when onnext, and then we can use the Action1 class.
action1<string> onnextaction = new action1<string> () {
@Override public
void Call (String s) {
System.out.println (s);
}
;
The Subscribe method has an overloaded version that accepts three Action1 types of arguments, corresponding to the Onnext,oncomplete, onerror functions.
Myobservable.subscribe (Onnextaction, onerroraction, oncompleteaction);
We don't care about onerror and oncomplete here, so we just need the first argument to
Myobservable.subscribe (onnextaction);
Outputs "Hello, world!"
The code above can eventually be written like this
Observable.just ("Hello, world!")
. Subscribe (new action1<string> () {
@Override public
void Call (String s) {
System.out.println (s);
}
});
Using Java8 's lambda can make your code simpler
Observable.just ("Hello, world!")
. Subscribe (s-> System.out.println (s));
In Android development, it's highly recommended to use the Retrolambda Gradle plugin so you can use lambda in your code.
Transform
Let's do something more interesting!
For example, I want to add my signature to Hello World, you might think of modifying the observable object:
Observable.just ("Hello, world! -dan ")
. Subscribe (S-> System.out.println (s));
If you can change the observable object, this is certainly OK, but what if you can't modify the observable object? For example, is the observable object provided by a Third-party library? For example, my observable object is subscribed to by multiple subscriber, but I just want to make a change to a subscriber?
So what about changing events in subscriber? For example, the following code:
Observable.just ("Hello, world!")
. Subscribe (s-> System.out.println (s + "-dan"));
This is still not satisfying because I want my subscribers to be as light as possible because I have the possibility to run subscriber in Mainthread. In addition, according to the concept of response function programming, subscribers should do is "response", in response to the events emitted by observable, rather than to modify it. If I can in some intermediate step to "Hello world! "Is it cool to make a transformation?"
Instance
We will use the weather map Open platform (OPENWEATHERMAP) API as a demo example. Openweathermap (http://api.openweathermap.org/) is a free weather data API that is very easy to configure and use, with only incoming location information (city name or geographic coordinates) as a parameter when invoked
It is usually necessary to implement a call to an API with the following steps (each step has a bunch of formulaic code):
Create the desired model class (add annotations, if necessary).
Implement request-response management of the network layer code with error handling.
Using a background thread to implement a request call (typically implemented as an asynchronous task), a callback function (Callback function) is implemented to render the response information on the UI thread.
Creating a Model class
The first step we can rely on some similar jsonschema2pojo json-pojo generation tool (half) automation to complete. The model classes for the Openweather API are as follows:
public class Weatherdata {public coordinates coord;
Public local SYS;
Public list<weather> Weathers;
public String Base;
public main main;
Public wind and wind;
Public rain rain;
Public Cloud clouds;
public long ID;
public long DT;
public String name;
public int cod;
public static class coordinates {public double lat;
public double lon;
public static class Local {public String country;
public long Sunrise;
public long sunset;
public static class Weather {public int id;
public String main;
public String description;
public String icon;
public static class Main {public double temp;
public double pressure;
public double humidity;
public double temp_min;
public double Temp_max;
public double sea_level;
public double grnd_level;
public static class Wind {public double speed;
public double deg; public static class, Rain {public int threehoUrforecast;
public static class Cloud {public int all;
}
}
Using retrofit to implement network calls
Implementation of network calls in the second step usually we need to write a bunch of formulaic code, but if you use the square Company's retrofit component (http://square.github.io/retrofit/), it will greatly reduce the amount of code. Just create an interface class (with annotations to describe the entire request), and then use Restadapter.builder to create the client. Retrofit can also be used to complete the serialization and deserialization of JSON.
Private interface Apimanagerservice {
@GET ("/weather")
weatherdata GetWeather (@Query ("Q") String place, @ Query ("units") String units);
As we can see in the example above, the comment before the method is made up of an HTTP method (we are using get, of course, you can also use retrofit to implement post, put, Delete and head methods) and a relative path (the basic path is provided by Restadapter.builder). @Query annotation is used to assemble the request parameters, we have two parameters, one is place (the position is represented) and the other is the units unit of measurement.
Let's take a look at a specific invocation example (the actual code should put this call into a non-UI line Chengri). This code is relatively easy to understand:
//...
Final Restadapter restadapter = new Restadapter.builder ()
. Setserver ("http://api.openweathermap.org/data/2.5")
. Build ();
Final Apimanagerservice Apimanager = restadapter.create (apimanagerservice.class);
Final Weatherdata weatherdata = Apimanager.getweather ("Budapest,hu", "metric");
//...
How, very simple, you only need very little code to achieve the entire call process, this is the power of retrofit
Implementation of responsive programming with Rxjava
Now we are in step three: the Rxjava part! Our example here will use it to implement an asynchronous request call.
First we need to change the interface class created earlier to this class:
public class Apimanager {private interface Apimanagerservice {@GET ("/weather") Weatherdata GetWeather (@Quer
Y ("q") string place, @Query ("units") string units); private static final Restadapter Restadapter = new Restadapter.builder (). Setserver ("HTTP://API.OPENWEATHERMAP.O
rg/data/2.5 "). Build ();
private static final Apimanagerservice Apimanager = restadapter.create (Apimanagerservice.class); public static observable<weatherdata> Getweatherdata (final String city) {return observable.create (new observabl E.onsubscribefunc<weatherdata> () {@Override public Subscription onsubscribe (observer<? Super Weather
Data> observer) {try {observer.onnext (Apimanager.getweather (City, "metric"));
Observer.oncompleted ();
catch (Exception e) {observer.onerror (e);
return Subscriptions.empty ();
}). Subscribeon (Schedulers.threadpoolforio ());
}
}
Let's take a look at the Getweatherdata () method, which calls the Observable.create () Method and passes a OBSERVABLE.ONSUBSCRIBEFUNC implementation to the method to get a observable object and return it. And once the observable object is subscribed (subscribed), it starts working. Observable the results of each processing are passed as arguments to the OnNext () method. Because we just want to implement the concurrent invocation of the network request, we just need to call one request per observable object. The code finally calls the OnComplete () method. The Subscribeon () method here is important, which determines which thread the program will use. This is called Schedulers.threadpoolforio (), which is used to optimize IO and network performance related work.
The final step is to implement this API call. The following code implements concurrent network requests, each using a different invocation parameter to invoke the same URL asynchronously:
Observable.from (cities)
. Mapmany (New func1<string, observable<weatherdata>> () {
@Override Public
observable<weatherdata> Call (String s) {return
apimanager.getweatherdata (s);
}
})
. Subscribeon (Schedulers.threadpoolforio ())
. Observeon (Androidschedulers.mainthread ())
. Subscribe (NEW Action1<weatherdata> () {
@Override public
void Call (Weatherdata weatherdata) {
//do your work
}
});
The Observable.from () method converts an array of city names to a observable object, providing the strings in the array to different threads. The Mapmany () method then converts each string provided by the former into a observable object (the new object contains the Weatherdata object data). The transformation here is done by calling Apimanager.getweatherdata ().
This is still registered on the I/O thread pool. On the Android system, if you need to display the results on the UI, you must publish the data to the UI threading process. Because we know that on Android only the most primitive thread that creates an interface can manipulate the interface. Here you only need to call Androidschedulers.mainthread () with the Observeon () method. The call to the subscribe () method triggers the observable object, where we can handle the results of the observable object.
This example shows the powerful features of Rxjava. If there is no Rx, we need to create n threads to invoke the request and then give the processing results asynchronously to the UI thread. Using RX, you just write very little code to do your job and use its powerful capabilities to create, merge, filter, and transform observable objects.
Rxjava can be used as a powerful tool to handle concurrency when developing Android apps. Although it still takes some time to be familiar with it, Maito, once mastered, will be of great help to you. The response extension Library is a good idea, and we've been using it for Android development for weeks (and in the near future, our product's asynchronous task processing will be entirely based on it). The more you learn about it, the more you will fall in love with it.