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 的一个接口,用于包装含有一个参数的方法。Func1Action 的区别在于, Func1 包装的是有返回值的方法。另外,和 ActionX 一样,FuncX 也有多个,用于不同参数个数的方法。FuncXActionX的区别在 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() 的原理是这样的:

  1. 使用传入的事件对象创建一个 Observable对象;

  2. 并不发送这个 Observable, 而是将它激活,于是它开始发送事件;

  3. 每一个创建出来的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()这一块,但是都没有理解,现在自己做笔记,然后看源码,虽然说不能百分百理解,但是也差不多了

0 1
原创粉丝点击