Responsive Function Programming_RxJava & RxAndroid
Home page:
https://github.com/ReactiveX/RxJava
Chinese material:
https://github.com/lzyzsd/Awesome-RxJava
https://www.zhihu.com/question/35511144
1. Purpose:
Asynchronous operation
You can still keep the logic of your code concise in cases where the logic of your program is exceptionally complex
Configuration: Add dependencies:
compile 'io.reactivex:rxjava:1.1.3'
compile 'io.reactivex:rxandroid:1.1.0'
If used in conjunction with Retrofit, the following dependencies need to be added
compile 'com.squareup.retrofit2:retrofit:2.0.1'
compile 'com.squareup.retrofit2:converter-gson:2.0.1'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'
2. Basic concepts:
(1) Observed: Observable Role: Determines when and how events will be triggered Create method: Observable.just(T...) parameter is single Observable.from(T[])/Observable.from(Iterable<? Extends T>) parameter is an array or Iterable (2) Observer Role: What happens when an event triggers The implementation class has Observer / Subscriber (3) Subscription: subscribe Role: Associate Observable with Observer Method: observable.subscribe(observer); observable.subscribe(subscriber); (4) Events: onNext(): Common events onCompleted(): End of event queue onError(): Event queue exception It is important to note that onCompleted() and onError() are mutually exclusive. Calling one of them should not trigger the other.
3. Cases:
Case 1: There is an existing array String[] arr ={"afdsa", "bfdsa", "cfda"}, find the string that starts with the letter "a" and add "from Alpha", and print out the length of the new string
private void simpleDemo() {
String[] arr = {"afdsa", "bfdsa", "cfda"};
//Method 2:
Observable
.from(arr)
.filter(new Func1<String, Boolean>() {
@Override
public Boolean call(String s) {
return s.startsWith("a");
}
})
.map(new Func1<String, String>() {
@Override
public String call(String s) {
return s + " from Alpha";
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
System.out.println("Rxjava:" + s.length());
}
});
//Method 1:
for (int i = 0; i < arr.length; i++) {
String temp = arr[i];
if (temp.startsWith("a")) {
temp += " from Alpha";
System.out.println("Normal:" + temp.length());
}
}
Case 2: Pictures are taken from a specified drawable file id and displayed in the ImageView, and Toast errors are printed when an exception occurs:
private void simpleDemo() {
final int drawID = R.mipmap.ic_launcher;
Observable
.create(new Observable.OnSubscribe<Drawable>() {
@Override
public void call(Subscriber<? super Drawable> subscriber) {
Drawable drawable = getResources().getDrawable(drawID);
subscriber.onNext(drawable);
subscriber.onCompleted();
}
})
.subscribe(new Observer<Drawable>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_SHORT).show();
}
@Override
public void onNext(Drawable drawable) {
imageView.setImageDrawable(drawable);
}
});
}
4.Scheduler
Role: Controls the thread. Specifies in which thread a piece of code runs. Built-in Scheduler: *Schedulers.immediate(): Runs directly on the current thread, equivalent to not specifying a thread.This is the default Scheduler. *Schedulers.newThread(): Always enable new threads and perform operations on them. *Schedulers.io(): Scheduler used for I/O operations (reading and writing files, reading and writing databases, network information exchange, etc.).The behavior pattern is similar to newThread(), except that the internal implementation of IO () uses an infinite number of upper-bound thread pools and can reuse idle threads, so in most cases IO () is more efficient than newThread().Don't put your calculations in io(), you can avoid creating unnecessary threads. *Schedulers.computation(): The Scheduler used for the calculation.This calculation refers to CPU-intensive computing, operations that are not limited by operations such as I/O, such as graphical computing.This Scheduler uses a fixed thread pool of CPU cores.Do not place I/O operations in computation (), otherwise the wait time for I/O operations will waste CPU. *Android Schedulers.mainThread(): Android-specific, which specifies that the operation will be run on the Android main thread. Specify the thread's method: Observable.subscribeOn(): Specifies the thread on which subscribe() occurs, that is, the thread on which Observable.OnSubscribe is activated.Or thread called event generation Observable.observeOn(): Specifies the thread on which Subscriber is running.Or a thread called event consumption.
5. Data transformation:
Role: is to process the object or the whole sequence of events into different events or sequence of events
Observable.map: one-to-one transformation
private void simpleDemo() {
Observable
.just(R.mipmap.ic_launcher)
.map(new Func1<Integer, Drawable>() {
@Override
public Drawable call(Integer integer) {
return getResources().getDrawable(integer);
}
})
.subscribe(new Action1<Drawable>() {
@Override
public void call(Drawable drawable) {
imageView.setImageDrawable(drawable);
}
});
}
Observable.flatMap: One-to-many conversion
public class Course {
private String name;
private int id;
public Course(String name, int id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
public class Student {
private String name;
private ArrayList<Course> courses;
public Student(String name, ArrayList<Course> courses) {
this.name = name;
this.courses = courses;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<Course> getCourses() {
return courses;
}
public void setCourses(ArrayList<Course> courses) {
this.courses = courses;
}
}
private void student() {
Course yuwen = new Course("Chinese", 1);
Course shuxue = new Course("Mathematics", 2);
Course yingyu = new Course("English", 3);
Course lishi = new Course("History", 4);
Course zhengzhi = new Course("Politics", 5);
Course xila = new Course("Greek", 6);
ArrayList<Course> course1 = new ArrayList<>();
course1.add(yuwen);
course1.add(shuxue);
course1.add(yingyu);
course1.add(lishi);
course1.add(zhengzhi);
course1.add(xila);
Student zhangsan = new Student("zhangsan", course1);
Observable.just(zhangsan)
.flatMap(new Func1<Student, Observable<Course>>() {
@Override
public Observable<Course> call(Student student) {
return Observable.from(student.getCourses());
}
})
.subscribe(new Action1<Course>() {
@Override
public void call(Course course) {
System.out.println(course.getName());
}
});
}
6. Use with Retrofit
Add dependencies:
compile 'com.squareup.retrofit2:retrofit:2.0.1'
compile 'com.squareup.retrofit2:converter-gson:2.0.1'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'
utilize http://www.jsonschema2pojo.org/ Create a data model
Create the REST API interface. Note that the return is not Call, but Observable.Example code:
public interface LocationInterface {
// http://ip.taobao.com/service/getIpInfo.php?ip=202.178.10.23
@GET("/service/getIpInfo.php")
public Observable<Location> getLocation(@Query("ip") String ip);
}
Create a Retrofit object and make a request. Note that Retrofit needs to add the addCallAdapterFactory at this point. Sample code:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE2)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
LocationInterface locationInterface = retrofit.create(LocationInterface.class);
Observable<Location> location = locationInterface.getLocation("8.8.8.8");
location
.subscribeOn(Schedulers.io())
.map(new Func1<Location, String>() {
@Override
public String call(Location location) {
return location.getData().getCountry();
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
textView.setText(s);
}
});