关于RxJava学习总结
一 ,RxJava 到底是什么?
一个词语: 异步。
RxJava 在GitHub主页上的自我介绍就是”a library for composing asynchronous and event-based programs using observable sequences for the Java VM”(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。
GitHub 地址 :
https://github.com/ReactiveX/RxJava
https://github.com/ReactiveX/RxAndroid
引入依赖:
compile 'io.reactivex:rxjava:1.1.3'
compile 'io.reactivex:rxandroid:1.1.0'
二,特点
(1) 观察者模式
RxJava 用到了设计模式中的观察者模式,支持数据或者事件序列,允许对序列进行组合, 并对线程,同步和并发数据结构进行了抽象。
(2)轻量级
无依赖库,Jar 包小于1M。
(3)支持多语言
支持Java 6+ 和android 2.3+ 。 RxJava 设计初衷就是兼容说的JVM语言, 目前支持的JVM语言就有Groovy,Clojure,JRbuy,Kotlin 和Scala 。
(4)多线程的支持
封装了各种并发实现,如Threads,pools.ecent loops ,fibers ,actors 。
三,RxJava 好在哪里? 简洁 ?
异步操作很关键的一点就是 程序的简洁性, 因为在调度过程比较复杂的情况下,异步代码经常会很难写也很难被读懂。Android创造了AsyncTask 和 Handler ,其实都是为了让异步代码更加简洁。RxJava的优势也是简洁,但它的简洁的与众不同之处在于,随着程序逻辑变的越来越复杂,它依然能够保持简洁。
举个列子:
假设有这样一个需求,界面上有一个自定义的视图imageCollectorView ,它的作用就是显示多张图片 , 并且能使用addImage(Bitmap)方法来任意增加显示的图片,现在需要程序将一个给出的目录数组File[] folders 中每个目录下的png 图片都加在出来并显示在imageCollectorView 中,需要注意的就是,由于读取图片的这一个过程会比较耗时,需要后台执行, 而且图片的显示则需要在UI线程中执行。
一般情况我们都会借助:Thread来实现。
new Thread() {
@Override
public void run() {
super.run();
for (File folder : folders) {
File[] files = folder.listFiles();
for (File file : files) {
if (file.getName().endsWith(".png")) {
final Bitmap bitmap = getBitmapFromFile(file);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
imageCollectorView.addImage(bitmap);
}
});
}
}
}
}
}.start();
而使用了RxJava,实现方式就是这样的:
Observable.from(folders)
.flatMap(new Func1<File, Observable<File>>() {
@Override
public Observable<File> call(File file) {
return Observable.from(file.listFiles());
}
})
.filter(new Func1<File, Boolean>() {
@Override
public Boolean call(File file) {
return file.getName().endsWith(".png");
}
})
.map(new Func1<File, Bitmap>() {
@Override
public Bitmap call(File file) {
return getBitmapFromFile(file);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Bitmap>() {
@Override
public void call(Bitmap bitmap) {
imageCollectorView.addImage(bitmap);
}
});
四,API介绍和原理简析
1,概念: 扩展的观察者模式
RxJava的异步实现,是通过一个扩展的观察者模式来实现的。
观察者模式:观察者模式面向的需求是:A对象(观察者)对B对象(被观察者)的某种变化高度敏感,需要在B变化的一瞬间做出来的反应。 举个例子:新闻里面喜闻乐见的警察抓小偷,警察需要在小偷伸手作案的时候实施抓捕。在这个列子中,警察是观察者,小偷是被观察者,警察需要时刻观察着小偷的一举一动,才能保证不会漏过任何瞬间。程序的观察者模式和这种真正的【观察】略有不同,观察者不需要时刻盯着被观察者(列如A不需要每过2ms就检查一下B的状态)而是采用注册(Register)或者 称为订阅(Subscribe)的方式,告诉被观察者,我需要你的XX状态,你要在它变化的时候通知我。 Android开发中一个比较典型的列子就是点击监听器OnClickListener 。对设置ClickListener来说,View 是被观察者,OnClickListener 是观察者,两者通过setOnClickListener() 方法来达成订阅关系。订阅之后用户点击按钮的瞬间,Android Framework 就会将点击事件发送给已经注册的OnClickListener 。才去这样的被动观察方式,既省去了反复检索状态资源的消耗,也能够得到更高的反馈速度。
OnClickListener 的模式大致如下图所示:
通过setOnClickListener () 方法,Button 持有OnClickListener 的引用,当用户点击是,Button自动调用OnClickListener 的OnClick()方法。 另外,如果把这张图中的概念抽象出来(Button -> 被观察者、OnClickListener -> 观察者、setOnClickListener() -> 订阅,onClick() -> 事件),就由专用的观察者模式(例如只用于监听控件点击)转变成了通用的观察者模式。如下图:
而 RxJava作为一个工具库, 使用的就是通用形式的观察者模式。
2,RxJava的观察者模式
RxJava 有四个基本概念:Observable (可观察者,即被观察者)、 Observer (观察者)、 subscribe (订阅)、事件。Observable 和 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer。
与传统观察者模式不同, RxJava 的事件回调方法除了普通事件 onNext() (相当于 onClick() /onEvent())之外,还定义了两个特殊的事件:onCompleted() 和 onError()。
onCompleted(): 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的 onNext() 发出时,需要触发 onCompleted() 方法作为标志。
onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
在一个正确运行的事件序列中, onCompleted() 和 onError() 有且只有一个,并且是事件序列中的最后一个。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。
2,基本实现
基于以上的概念,RxJava的基本实现主要有三点:
① ,创建Observer
Observer即观察者,它决定事件触发的时候将有怎样的行为,RxJava 中的 Observer接口的实现方式:
Observer<String> observer = new Observer<String>() {
@Override
public void onNext(String s) {
Log.d(tag, "Item: " + s);
}
@Override
public void onCompleted() {
Log.d(tag, "Completed!");
}
@Override
public void onError(Throwable e) {
Log.d(tag, "Error!");
}
};
除了 Observer 接口之外,RxJava 还内置了一个实现了 Observer 的抽象类:Subscriber。 Subscriber 对 Observer 接口进行了一些扩展,但他们的基本使用方式是完全一样的:
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onNext(String s) {
Log.d(tag, "Item: " + s);
}
@Override
public void onCompleted() {
Log.d(tag, "Completed!");
}
@Override
public void onError(Throwable e) {
Log.d(tag, "Error!");
}
};
未完!