【源码阅读】阅读 "RxJava 阅读笔记" 笔记

RxJava是什么

是一个异步库

RxJava好处是什么

让代码简洁,有序

RxJava的一些概念

  1. 重构的观察者
    普通的观察者 ObserverObservable ,构成观察者-被观察者关系后,观察者回调方法只有一个。

而RxJava 的观察者增加了

  • onNext 表示事件响应后,下一步操作
  • onError 表示事件内部处理出错。
  • onComplete 或者成功完成观察者的回调。
  1. RxJava 的观察者包含 Observer 和 另一个替代 ObserverSubscriber

  2. RxJava 有4个新增概念:观察者(Observer),被观察者(Observable),事件,订阅(subscribe)。

RxJava的基本用法

1. 首先要创建一个观察者 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!");
    }
};

RxJava提供了一个可替换的 观察者 : Subscriber , 基本实现和Observer类似,也有些基本区别:

  1. onStart(): 这是 Subscriber 增加的方法。它会在 subscribe 刚开始,而事件还未发送之前被调用,可以用于做一些准备工作,例如数据的清零或重置。这是一个可选方法,默认情况下它的实现为空。需要注意的是,如果对准备工作的线程有要求(例如弹出一个显示进度的对话框,这必须在主线程执行), onStart() 就不适用了,因为它总是在 subscribe 所发生的线程被调用,而不能指定线程。要在指定的线程来做准备工作,可以使用 doOnSubscribe() 方法,具体可以在后面的文中看到。
  2. unsubscribe(): 这是 Subscriber 所实现的另一个接口 Subscription 的方法,用于取消订阅。在这个方法被调用后,Subscriber 将不再接收事件。一般在这个方法调用前,可以使用 isUnsubscribed() 先判断一下状态。 unsubscribe() 这个方法很重要,因为在 subscribe() 之后, Observable 会持有 Subscriber 的引用,这个引用如果不能及时被释放,将有内存泄露的风险。所以最好保持一个原则:要在不再使用的时候尽快在合适的地方(例如 onPause() onStop() 等方法中)调用 unsubscribe() 来解除引用关系,以避免内存泄露的发生。

2. 创建被观察者

Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("Hello");
        subscriber.onNext("Hi");
        subscriber.onNext("Aloha");
        subscriber.onCompleted();
    }
});

看到上面的Observable.OnSubscribe接口没,就是他最终调用了 subscriber 的事件发送方法onNext(), onCompleted()等。

3. 使用subscribe方法让二者建立订阅关系

observable.subscribe(observer);

以上,就建立了观察者和被观察者之间的订阅关系
其实现代码,也给一下, 后面会用到:

// 注意:这不是 subscribe() 的源码,而是将源码中与性能、兼容性、扩展性有关的代码剔除后的核心代码。
// 如果需要看源码,可以去 RxJava 的 GitHub 仓库下载。
public Subscription subscribe(Subscriber subscriber) {
    subscriber.onStart();
    onSubscribe.call(subscriber);
    return subscriber;
}

除了上面的那种 Observer, 还可以给subcribe()方法传入不完整的接口:

Action1<String> onNextAction = new Action1<String>() {
    // onNext()
    @Override
    public void call(String s) {
        Log.d(tag, s);
    }
};
Action1<Throwable> onErrorAction = new Action1<Throwable>() {
    // onError()
    @Override
    public void call(Throwable throwable) {
        // Error handling
    }
};
Action0 onCompletedAction = new Action0() {
    // onCompleted()
    @Override
    public void call() {
        Log.d(tag, "completed");
    }
};

// 自动创建 Subscriber ,并使用 onNextAction 来定义 onNext()
observable.subscribe(onNextAction);
// 自动创建 Subscriber ,并使用 onNextAction 和 onErrorAction 来定义 onNext() 和 onError()
observable.subscribe(onNextAction, onErrorAction);
// 自动创建 Subscriber ,并使用 onNextAction、 onErrorAction 和 onCompletedAction 来定义 onNext()、 onError() 和 onCompleted()
observable.subscribe(onNextAction, onErrorAction, onCompletedAction);

上面的Action0, Action1, Action2 ,就是RxJava提供的自定义类型接口。都可以匿名内部类对象的形式,传给observable.subscribe(). Action0 提供一个 call() 无参无返回值的方法, Action1 的call方法会多一个参数,他们都是对 onComplete()方法的包装,而已,最终,会回调到 call()方法。(ps:RxJava2 好像去掉这个Action0了)

4. 创建事件序列

有了观察者,被观察者之间的订阅关系,还需要产生事件,在观察者和被观察者之间流动对吧,所以RxJava提供了

  • create(“Hello”, “Hi”, “Aloha”)
  • just(…)
  • from(“Hello”, “Hi”, “Aloha”"")
    等方法,去创造事件序列

Scheduler

一般使用RxJava时,我们这样用:

int drawableRes = ...;
ImageView imageView = ...;
Observable.create(new OnSubscribe<Drawable>() {
    @Override
    public void call(Subscriber<? super Drawable> subscriber) {
    
        Drawable drawable = getTheme().getDrawable(drawableRes));
        // 产生事件的位置
        subscriber.onNext(drawable);
        subscriber.onCompleted();
    }
})
.subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程
.observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
.subscribe(new Observer<Drawable>() {
    @Override
    public void onNext(Drawable drawable) {
    // 消耗事件的位置
        imageView.setImageDrawable(drawable);
    }

    @Override
    public void onCompleted() {
    }

    @Override
    public void onError(Throwable e) {
        Toast.makeText(activity, "Error!", Toast.LENGTH_SHORT).show();
    }
});

上面,通过调用 subscribeOn(Schedulers.io()), .observeOn(AndroidSchedulers.mainThread()), 我们可以指定执行产生事件的线程Schedulers.io(), 消耗事件回调方法所在的线程AndroidSchedulers.mainThread(),那RxJava是如何做到的呢?

首先,我们要理解它的一个方法(或者叫概念,又是概念)

变换事件

RxJava内部,通过一个稍显复杂的操作,可以“将事件序列中的对象或整个序列进行加工处理,转换成不同的事件或事件序列“,

事件序列是啥?先来一段代码:

Observable.just("images/logo.png") // 输入类型 String
    .map(new Func1<String, Bitmap>() {
        @Override
        public Bitmap call(String filePath) { // 参数类型 String
        // 位置1
            return getBitmapFromPath(filePath); // 返回类型 Bitmap
        }
    })
    .subscribe(new Action1<Bitmap>() {
        @Override
        public void call(Bitmap bitmap) { // 参数类型 Bitmap
        // 位置2
            showBitmap(bitmap);
        }
    });

上面的 new Func1(), 还有 new Aciton1() 匿名类对象,都是 事件,他们会有一些事件方法,方法的参数,看着不同啊,那,代码为何可以从一个方法跳到另一个方法**(位置1 -》 位置2)**执行呢?

原因就是有 map() 这个方法。他可以将一个事件或者事件序列变换成另一个事件或者事件序列
具体的原理呢,后续会讲到(也可能讲不到)。~~!

总之,这个map()方法非常重要,也非常牛逼,先记住:map()做到了事件或者事件序列的转换。

当然, 还有其他方法,map方法更牛逼:

  • flatMap() 非常6的一个方法,解释起来都困难(暂时不解释了),和map的区别是:变换后返回值是一个Observable对象。
  • throttleFirst() 每次事件触发后的一定时间间隔内丢弃新的事件。常用作去抖动过滤,例如按钮的点击监听器:

变换的原理

这一段最绕了。不过还是可以看一看。

  • 变换虽然功能各有不同,但实质上都是针对事件序列的处理和再发送。而在 RxJava 的内部,它们是基于同一个基础的变换方法: lift(Operator)。

代码1

// 注意:这不是 lift() 的源码,而是将源码中与性能、兼容性、扩展性有关的代码剔除后的核心代码。
// 如果需要看源码,可以去 RxJava 的 GitHub 仓库下载。
public <R> Observable<R> lift(Operator<? extends R, ? super T> operator) {
    return Observable.create(new OnSubscribe<R>() {
        @Override
        public void call(Subscriber subscriber) {
            Subscriber newSubscriber = operator.call(subscriber);
            newSubscriber.onStart();
            onSubscribe.call(newSubscriber);
        }
    });
}

上面一段代码发生了神马?为什么就可以执行变换事件或者事件序列的牛皮操作呢?

这里,我把之前 subscribe()方法也拷过来,对比一下:

代码2

// 注意:这不是 subscribe() 的源码,而是将源码中与性能、兼容性、扩展性有关的代码剔除后的核心代码。
// 如果需要看源码,可以去 RxJava 的 GitHub 仓库下载。
public Subscription subscribe(Subscriber subscriber) {
    subscriber.onStart();
    onSubscribe.call(subscriber);
    return subscriber;
}

这里,代码1那段call()方法几乎和代码2subscribe()方法类似 ,新生成了一个 newSubscriber(前面说过,等价于 Observer), 然后调用 onStart()方法,把 newSubscriber 关联到旧的 onSubscribe 对象中。

  • subscribe() 中这句话的 onSubscribe 指的是 Observable 中的 onSubscribe 对象,是否还记得create 方法?
  • 当含有 lift() 时:
    1. lift() 创建了一个 Observable 后,加上之前的原始 Observable,已经有两个 Observable 了;

    2. 而同样地,新 Observable 里的新 OnSubscribe 加上之前的原始 Observable 中的原始 OnSubscribe,也就有了两个 OnSubscribe;

    3. 当用户调用经过 lift() 后的 Observable 的 subscribe() 的时候,使用的是 lift() 所返回的新的 Observable ,于是它所触发的 onSubscribe.call(subscriber),也是用的新 Observable 中的新 OnSubscribe,即在 lift() 中生成的那个 OnSubscribe;

    4. 而这个新 OnSubscribe 的 call() 方法中的 onSubscribe ,就是指的原始 Observable 中的原始 OnSubscribe ,在这个 call()方法里,新 OnSubscribe 利用 operator.call(subscriber) 生成了一个新的 Subscriber(Operator 就是在这里,通过自己的 call() 方法将新 Subscriber 和原始 Subscriber 进行关联,并插入自己的『变换』代码以实现变换),然后利用这个新 Subscriber 向原始 Observable 进行订阅。
      这样就实现了 lift() 过程,有点像一种代理机制,通过事件拦截和处理实现事件序列的变换。

第4点太绕了。

用自己的话描述,就是: Observable 执行了lift操作,形成一个新的Observable对象,代理了旧的Observable,有事件过来,先通过新的,转发给旧的,旧的再通知代理的 Subscriber. 最后再分发给 目标 Subscriber

还是打个比方吧:

有个卖房子的中介毛利小O, 现在有个人Subscriber要找他买房子,但是他没有房源;
于是,他只能找售楼部的中介 工藤新O, 中介 毛利小O 的买房人就成为工藤新OSubscriber。but!中介 工藤新O很聪明,他要搞个操作对毛利小O的买房人(旧的Subscriber)进行一层关联和变换。即:operator.call(subscriber)。生成一个新的Subscriber, 并且里面有自己的一些操作。然后调用onSubscribe.call(newSubscriber) 把新的和旧的进行一个关联。

接着,中介 工藤新O 就能利用新的Subscriber,实现自己的目的了(对房价实现一些不可告人的操作)了。

线程控制的原理

to be continue

参考:
给 Android 开发者的 RxJava 详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值