RxJava 学习笔记(三)
来源:互联网 发布:monaco for windows 编辑:程序博客网 时间:2024/06/11 15:46
我只是搬运工,本来想自己写,但是理解和语言表达真心过不了关,
源码方面,我详细点介绍,
笔记么,好东西我就抄 给 Android 开发者的 RxJava 详解
线程控制Scheduler
1)Scheduler的API
在不指定线程的情况下, RxJava 遵循的是线程不变的原则,即:在哪个线程调用 subscribe()
,就在哪个线程生产事件;在哪个线程生产事件,就在哪个线程消费事件。如果需要切换线程,就需要用到 Scheduler
(调度器)。
Schedulers.immediate():
直接在当前线程运行,相当于不指定线程。这是默认的Scheduler
。Schedulers.newThread():
总是启用新线程,并在新线程执行操作。Schedulers.io():
I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的Scheduler
。行为模式和newThread()
差不多,区别在于io()
的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下io()
比newThread()
更有效率。不要把计算工作放在io()
中,可以避免创建不必要的线程。Schedulers.computation():
计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个Scheduler
使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在computation()
中,否则 I/O 操作的等待时间会浪费 CPU。- 另外,
Android
还有一个专用的AndroidSchedulers.mainThread()
,它指定的操作将在 Android 主线程运行。
有了这几个 Scheduler ,就可以使用 subscribeOn() 和 observeOn() 两个方法来对线程进行控制了。
subscribeOn()
: 指定 subscribe() 所发生的线程,即 Observable.OnSubscribe 被激活时所处的线程。或者叫做事件产生的线程。observeOn()
: 指定 Subscriber 所运行在的线程。或者叫做事件消费的线程。
Observable.just(1, 2, 3, 4) .subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程 .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程 .subscribe(new Action1<Integer>() { @Override public void call(Integer number) { Log.d(tag, "number:" + number); } });
这个其实可以配合compose 使用 下一篇介绍
变换 (也是个人感觉掌握了这个就算入门了)
1)API
- map():事件对象的直接变换
Observable.just("images/logo.png") // 输入类型 String .map(new Func1<String, Bitmap>() { @Override public Bitmap call(String filePath) { // 参数类型 String return getBitmapFromPath(filePath); // 返回类型 Bitmap } }) .subscribe(new Action1<Bitmap>() { @Override public void call(Bitmap bitmap) { // 参数类型 Bitmap showBitmap(bitmap); } });
这里出现了一个叫做 Func1
的类。它和 Action1
非常相似,也是 RxJava 的一个接口,用于包装含有一个参数的方法。Func1
和 Action
的区别在于, Func1 包装的是有返回值
的方法。另外,和 ActionX
一样,FuncX
也有多个,用于不同参数个数的方法。FuncX
和 ActionX
的区别在 FuncX
包装的是有返回值的方法。
- flatMap()
Student[] students = ...;Subscriber<Course> subscriber = new Subscriber<Course>() { @Override public void onNext(Course course) { Log.d(tag, course.getName()); } ...};Observable.from(students) .flatMap(new Func1<Student, Observable<Course>>() { @Override public Observable<Course> call(Student student) { return Observable.from(student.getCourses()); } }) .subscribe(subscriber);
从上面的代码可以看出,flatMap()
和map()
有一个相同点:它也是把传入的参数转化之后返回另一个对象。但需要注意,和map()
不同的是, flatMap()
中返回的是个Observable
对象,并且这个Observable
对象并不是被直接发送到了Subscriber
的回调方法中。 flatMap()
的原理是这样的:
使用传入的事件对象创建一个
Observable
对象;并不发送这个
Observable
, 而是将它激活,于是它开始发送事件;- 每一个创建出来的
Observable
发送的事件,都被汇入同一个Observable
,而这个Observable
负责将这些事件统一交给Subscriber
的回调方法。这三个步骤,把事件拆成了两级,通过一组新创建的Observable
将初始的对象『铺平』之后通过统一路径分发了下去。而这个『铺平』就是flatMap()
所谓的 flat。
2) 变换的原理:lift()
这些变换虽然功能各有不同,但实质上都是针对事件序列的处理和再发送
。而在 RxJava 的内部,它们是基于同一个基础的变换方法: lift(Operator)。首先看一下 lift() 的内部实现(仅核心代码):
- 下面是
map()
方法的 内部实现 ,flatmap()
其实就是类似 最后也是用到lift()
// 比如 String 转为 Bitmap ,这样 T 为 String R 为 Bitmappublic final <R> Observable<R> map(Func1<? super T, ? extends R> func) { // 看到没有 ,return lift(new OperatorMap<String , Bitmap>) 注意类型 return lift(new OperatorMap<T, R>(func)); }public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) { // <String,Bitmap> // 看到没有 返回的是 Observable<String> ,你可能会疑惑 为什么不是 Observable<Bitmap> , // 不是要String 转为Bitmap吗 ? // 如果你是这样想就错了哦,我们这个是 对于map()的内部实现,他并没有转为Observalbe<Bitmap>,而是一个新的Observable<String> // 这边生成 了新的 被观察者 Observable<String> return new Observable<R>(new OnSubscribe<R>() { @Override public void call(Subscriber<? super R> o) { try { // ① hook.onLift其实就是直接返回operator // 重写这个方法 ,可以被修改,装饰,或者只是取代作为传送的返回, // 然后调用 call方法 o的类型为 String /* ② public interface Func1<T, R> extends Function { // Bitmap call(Stirng t) 这边就是重点,就是在这边他做了转化,我们就是在这个方法里面 进行自定义的转化 R call(T t); } */ // 这边生成了 第二个 新的 观察者Subscriber<Bitmap> Subscriber<? super T> st = hook.onLift(operator).call(o); try { // 这边调用 Subscriber<Bitmap> 的 onStart() st.onStart(); // 在 Observable 执行了 lift(Operator) 方法之后,会返回一个新的 Observable, // 这个新的 Observable 会像一个代理一样,负责接收原始的 Observable 发出的事件, // 并在处理后发送给 Subscriber --》 这边是个Action1 onSubscribe.call(st); } catch (Throwable e) { Exceptions.throwIfFatal(e); st.onError(e); } } catch (Throwable e) { Exceptions.throwIfFatal(e); o.onError(e); } } }); } //***************************************************************************************** final OnSubscribe<T> onSubscribe; /** * 其实 onSubscribe 是Action1 ,这就是为什么 我们的 观察者可以直接使用 new Action1 * Action1<Subscriber<? super T>> 我惊呆了,他的类型是一个 Subscriber, * 真J8巧妙,我之前还怀疑, 上面那段代码 的onSubscribe.call(st); 难道只能是Action1,那为什么Sbucribe也可以? * 所以东西还是要清楚,看下来,才知道,才能理解透彻一点 */ public interface OnSubscribe<T> extends Action1<Subscriber<? super T>> { // cover for generics insanity } /** * 其实 operator 是 Func1 , 这就是为什么 我们 map中是 new Func1 */ public interface Operator<R, T> extends Func1<Subscriber<? super R>, Subscriber<? super T>> { // cover for generics insanity }
- 这边算是对 RxJava 学习笔记(二)订阅部分的源码补充吧
- 在 被观察者Observable 中, subscribe方法 有多种参数,结合上面的源码这样你应该可以理解为什么可以用onSubscribe.call(str)
public final Subscription subscribe(final Observer<? super T> observer) { if (observer instanceof Subscriber) { return subscribe((Subscriber<? super T>)observer); } return subscribe(new Subscriber<T>() { @Override public void onCompleted() { observer.onCompleted(); } @Override public void onError(Throwable e) { observer.onError(e); } @Override public void onNext(T t) { observer.onNext(t); } }); } // 就是这边 public final Subscription subscribe(final Action1<? super T> onNext) { if (onNext == null) { throw new IllegalArgumentException("onNext can not be null"); } return subscribe(new Subscriber<T>() { @Override public final void onCompleted() { // do nothing } @Override public final void onError(Throwable e) { throw new OnErrorNotImplementedException(e); } @Override public final void onNext(T args) { onNext.call(args); } }); } public final Subscription subscribe(final Action1<? super T> onNext, final Action1<Throwable> onError) { if (onNext == null) { throw new IllegalArgumentException("onNext can not be null"); } if (onError == null) { throw new IllegalArgumentException("onError can not be null"); } return subscribe(new Subscriber<T>() { @Override public final void onCompleted() { // do nothing } @Override public final void onError(Throwable e) { onError.call(e); } @Override public final void onNext(T args) { onNext.call(args); } }); } public final Subscription subscribe(final Action1<? super T> onNext, final Action1<Throwable> onError, final Action0 onComplete) { if (onNext == null) { throw new IllegalArgumentException("onNext can not be null"); } if (onError == null) { throw new IllegalArgumentException("onError can not be null"); } if (onComplete == null) { throw new IllegalArgumentException("onComplete can not be null"); } return subscribe(new Subscriber<T>() { @Override public final void onCompleted() { onComplete.call(); } @Override public final void onError(Throwable e) { onError.call(e); } @Override public final void onNext(T args) { onNext.call(args); } }); }
文章开头那篇文章,我之前看了很多次 在lift()
这一块,但是都没有理解,现在自己做笔记,然后看源码,虽然说不能百分百理解,但是也差不多了
- RxJava 学习笔记(三)
- RxJava学习笔记(三)--- 线程调度Scheduler
- RxJava学习笔记(三)自定义操作符
- RXJava学习笔记(1)
- RXJava学习笔记(2)
- RXJava学习笔记(3)
- RxJava 学习笔记(一)
- RxJava 学习笔记(二)
- RxJava 学习笔记(四)
- RxJava学习笔记(一)
- RxJava学习笔记(一)
- Android框架学习之RxJava(三)
- RxJava学习(三)
- RxJava学习笔记(一)--- 基础篇
- RxJava学习笔记(二)--- 操作符
- RxJava学习笔记(一)概念
- RxJava学习笔记(二)操作符
- RxJava学习笔记之初识(一)
- shell脚本的组合运用
- 恢复centos7与windows7系统引导方法-亲测可用
- 细节积累
- 实时报警触发器
- Mysql JDBC Url参数说明
- RxJava 学习笔记(三)
- 静态类,静态函数,静态变量
- Java获取路径
- python的正则表达式
- 【StringUtils】判断字符串是否有值,判断多个字符串是否相等
- 嵌入式学习-uboot-lesson5-点亮LED
- 随机生成指定位数的验证码
- 文章标题
- 【Python学习日记】生成器 和 迭代器