RxJava学习笔记
RxJava是目前非常流行的一个框架,通过监听者模式,可快速、方便、且代码通俗易懂地实现很多功能,代码非常优雅。它还有个非常大的好处,就是可以随意切换线程
- 基础概念
RxJava最核心的两个东西是Observables(被观察者,事件源)和Subscribers(观察者)。Observables发出一系列事件,Subscribers处理这些事件。这里的事件可以是任何你感兴趣的东西(触摸事件,web接口调用返回的数据。。。)
一个Observable可以发出零个或者多个事件,知道结束或者出错。每发出一个事件,就会调用它的Subscriber的onNext方法,最后调用Subscriber.onNext()或者Subscriber.onError()结束。
Rxjava的看起来很想设计模式中的观察者模式,但是有一点明显不同,那就是如果一个Observerble没有任何的的Subscriber,那么这个Observable是不会发出任何事件的。
- 基础用法
Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("hello");
subscriber.onNext("world");
subscriber.onCompleted();
}});
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onCompleted() {
Log.i(TAG,"completed");
}
@Override
public void onError(Throwable e) {
Log.i(TAG,"onError");
}
@Override
public void onNext(String s) {
Log.i(TAG,"s = " + s);
}};
observable.subscribe(subscriber);
- 进阶用法
初看代码,RxJava代码好复杂,一点也不优雅,代码量较大,事实上RxJava推崇的是链式调用,为了达到这个目的RxJava作了许多改进,添加了很多人性化的接口。
Observable的from方法,以及just方法,直接就能生成Observable且将数据传递给订阅者,不需要通过create了,也不需要再写冗长的OnSubscribe了。
Subscriber,有点类似于java中线程,当我们向线程池中提交一个任务给线程池,并不需要向线程池中提交一个Thread,只需要提交一个Runnable即可。那么,关于Subscriber,我们可以使用Action代码,Action的类有多个,根据需求选择。
Observable.just("tom","green")
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.i(TAG," just s = " + s);
}
});
上述代码可成功实现第一个例子的功能,但代码量非常小,看起来非常舒服。
- 变换
变换是RxJava非常犀利的功能,也是RxJava中非常难以理解的一项内容。常见的变换操作符常有map,flatmap等。
Observable向Subscriber发送数据,供Subscriber使用处理,如果Subscriber想要的数据并不是Observable发送的,这时就需要使用变换了。比如说,加载网络图片时,Observable可以向Subscriber传递一个网络地址,Subscriber自己读取网络地址上的图片。但是RxJava中极少看到这类写法,因为RxJava推崇的是链式调用,最好能直接将Bitmap传给Subscriber。此时变换就可大展身手了。
变换最重要的作用就是将数据源变成订阅者想要的数据,以符合链式调用原则。
Observable.just("tom","green")
.map(new Func1<String, Integer>() {
@Override
public Integer call(String s) {
return 0;
}
})
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer s) {
Log.i(TAG," just s = " + s);
}
});
上例中通过map变换将String类型的数据源变换成Integer类型的数据源。map方法,将Observable变成另外一个Observable,向自己的订阅者传递新的类型的数据。
ps:所有的泛型中都不能使用基础数据类型,int之类的不能使用,否则会报错。
flatmap和map类似,它的功能则是将一个Observable变成许多个Observable,想象一个场景,打印当前文件夹下所有文件的名字,此时则可以使用flatmap了,通过flatmap将文件夹路径下所有的文件列出来,将文件名传给订阅者,具体代码,读者可以尝试实现下。
- 线程切换
RxJava神奇的地方,还在于可以非常方便地切换线程,比如可以将耗时的操作放在工作线程中完成,更新UI的部分则放在主线程中完成,只需要一行代码即可,非常地方便。
- subscribeOn
它用于指定Observable处理数据时所在的线程 - observeOn
它用于指定订阅者处理Observable发送过来的数据时所在的线程
非常重要的一点,RxJava中遵循链式调用法则,那么它的代码顺序非常重要,虽然以上两个方法分别指定不同过程的线程,但也不能随便写,只有在对应的时刻写以上两个方法,才有效果。
具体来说,subscribeOn中指定的是耗时工作完成的线程,这类耗时工作常在变换过程当中,比如map之类。而observeOn方法中常用于指定在主线程内更新UI的内容。它们的调用时机一定要把握好,不能随意都写,否则会无效。
Observable.just(res)
.subscribeOn(Schedulers.io())
.map(new Func1<String, Bitmap>() {
@Override
public Bitmap call(String s) {
Log.i(TAG,"func1 s = " + s + " t.name = " + Thread.currentThread().getName());
return getBitmap(s);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Bitmap>() {
@Override
public void call(Bitmap bitmap) {
Log.i(TAG,"action " + " t.name = " + Thread.currentThread().getName());
mImg.setImageBitmap(bitmap);
}
});
RxJava中的内容还非常地多,本人记录的只是基础知识,具体的原理、开源代码走读待日后完成,更多地变换内容日后添加,有问题欢迎留言讨论。
邮箱:okunu@qq.com