RxJava(一) create 操作符的用法和源码分析

15 篇文章 42 订阅

RxJava系列文章目录导读:

一、RxJava create 操作符的用法和源码分析
二、RxJava map 操作符用法详解
三、RxJava flatMap 操作符用法详解
四、RxJava concatMap 操作符用法详解
五、RxJava onErrorResumeNext 操作符实现 app 与服务器间 token 机制
六、RxJava retryWhen 操作符实现错误重试机制
七、RxJava 使用 debounce 操作符优化 app 搜索功能
八、RxJava concat 操作处理多数据源
九、RxJava zip 操作符在 Android 中的实际使用场景
十、RxJava switchIfEmpty 操作符实现 Android 检查本地缓存逻辑判断
十一、RxJava defer 操作符实现代码支持链式调用
十二、combineLatest 操作符的高级使用
十三、RxJava 导致 Fragment Activity 内存泄漏问题
十四、interval、takeWhile 操作符实现获取验证码功能
十五、RxJava 线程的自由切换

1. create 操作符的基本使用

顾名思义,Create 操作符是用来创建一个 Observable 的。下面来看一个简单的代码段:

Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            //Emit Data
        }
})

create 方法接收一个参数Observable.OnSubscribe 来看下它的源码:

    /**
     * Invoked when Observable.subscribe is called.
     */
    public interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
        // cover for generics insanity
    }

Observable.OnSubscribe 说白了就是一个继承了 Action1 接口的接口:

public interface Action1<T> extends Action {
    void call(T t);
}

/**
 * All Action interfaces extend from this.
 * <p>
 * Marker interface to allow instanceof checks.
 */
public interface Action extends Function {

}
/**
 * All Func and Action interfaces extend from this.
 * <p>
 * Marker interface to allow instanceof checks.
 */
public interface Function {

}

它们的继承关系如下:Observable.OnSubscribe <- Action1 <- Action <- Function

create() 方法也就是个工厂方法:

public static <T> Observable<T> create(OnSubscribe<T> f) {
    return new Observable<T>(hook.onCreate(f));
}

通过 OnSubscribe 的源码的注释
Invoked when Observable.subscribe is called. 意思是 当 Observable 被订阅(Subscribe)
OnSubscribe 接口的 call 方法会被执行。

知道如何创建 Observable, 接下来我们看下如何订阅它:

Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        for (int i = 0; i < 5; i++) {
            printLog(tvLogs, "Emit Data:", i + "");
            subscriber.onNext("" + i);
        }
    }
})
.subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        //showToast(s);
        printLog(tvLogs, "Consume Data:", s);
    }
});

当调用了 subscribe 方法 Observable.OnSubscribe 的 call 方法就会被执行,在 Observable.OnSubscribe 的 call 方法中循环了调用了 5 次 subscriber.onNext,在 subscribe 的 Action1 回调就会接受 5 次回调。

Emit Data:'0' , Thread Name:RxCachedThreadScheduler-1
Emit Data:'1' , Thread Name:RxCachedThreadScheduler-1
Emit Data:'2' , Thread Name:RxCachedThreadScheduler-1
Emit Data:'3' , Thread Name:RxCachedThreadScheduler-1
Emit Data:'4' , Thread Name:RxCachedThreadScheduler-1
Consume Data:'0' , Thread Name:main
Consume Data:'1' , Thread Name:main
Consume Data:'2' , Thread Name:main
Consume Data:'3' , Thread Name:main
Consume Data:'4' , Thread Name:main

从输出的日志可以看到,我们还打印了线程的名称,我们可以控制发送数据、消费数据所在的线程。

.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())

subscribeOn 设置Observable的call方法所在的线程 【生产数据】

observeOn 设置subscribe的call方法所在的线程【消费数据】

2. 从源码角度分析 create() 和subscribe() 如何协同工作的

从上面的分析我们知道,create 方法就是一个简单的工厂方法:

public static <T> Observable<T> create(OnSubscribe<T> f) {
    return new Observable<T>(hook.onCreate(f));
}

直接new一个Observable 接收的参数由 hook.onCreate方 法返回(该方法也很简单):

public <T> OnSubscribe<T> onCreate(OnSubscribe<T> f) {
    return f;
}
protected Observable(OnSubscribe<T> f) {
    this.onSubscribe = f;
}

总结下来一句话:create 操作符创建 Observable,Observable 通过构造方法 保存了我们传进来的 OnSubscribe 说白了就是 Action1.

下面来看看 Observable 的 subscribe 方法的源代码:

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);
            }
        });
    }

从源码可以看出 subscribe 方法并没有直接调用传进来参数的方法(没有直接调用onNext.call())。
而是通过 subscribe(Subscriber) 方法, subscribe(Subscriber) 方法又是调用了Observable 的私有静态方法:private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) 。下面是该方法的源码片段:

private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
        
		//remove some code ....

        
        try {
            // allow the hook to intercept and/or decorate
            hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);
            return hook.onSubscribeReturn(subscriber);
        } catch (Throwable e) {
            // special handling for certain Throwable/Error/Exception types
            Exceptions.throwIfFatal(e);
            // if an unhandled error occurs executing the onSubscribe we will propagate it
            try {
                subscriber.onError(hook.onSubscribeError(e));
            } catch (Throwable e2) {
                Exceptions.throwIfFatal(e2);
                // if this happens it means the onError itself failed (perhaps an invalid function implementation)
                // so we are unable to propagate the error correctly and will just throw
                RuntimeException r = new RuntimeException("Error occurred attempting to subscribe [" + e.getMessage() + "] and then again while trying to pass to onError.", e2);
                // TODO could the hook be the cause of the error in the on error handling.
                hook.onSubscribeError(r);
                // TODO why aren't we throwing the hook's return value.
                throw r;
            }
            return Subscriptions.unsubscribed();
        }
    }

我们看关键部分就可以了:hook.onSubscribeStart(observable,observable.onSubscribe).call(subscriber);
看看 hook.onSubscribeStart 源码:

  public <T> OnSubscribe<T> onSubscribeStart(Observable<? extends T> observableInstance, final OnSubscribe<T> onSubscribe) {
      // pass-thru by default
      return onSubscribe;
  }

很简单,直接返回传递过来的参数(onSubscribe)。 这个 OnSubscribe 就是我们 Observable.create(OnSubscribe)传递进去的 OnSubscribe,然后调用 OnSubscribe 的 call。
所以上面的代码可以简化为(便于理解):observable.onSubscribe.call(subscriber).

至此,验证了那句话,只有当 Observable 被订阅 OnSubscribe 的 call(subscriber) 方法才会被执行。

我们知道了 OnSubscribe 的 call(subscriber) 执行的时机,那么是如何把生产的数据传递了 Observable.subscribe 方法的回调的呢?
我们通过 Observable.subscribe 源码得知,传递进来的回调 (Action1), 是通过Subscriber 来执行 Action1 的回调,Subscriber 又是 Observable.create() 参数的回调。

Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            //Emit Data
        }
})

所以 Subscriber 是 Observable.OnSubscribe 的回调和 Observable.subscribe(Action1…) 的 Action1 之间通信的桥梁。

Subscriber 有三个方法:

  • onCompleted();
  • void onError(Throwable e);
  • void onNext(T t);

既然 Subscriber 是 Observable.create(params) 参数的回调和 Observable.subscribe()参数回调的通信桥梁,Subscriber 有三个方法,那么 Observable.subscribe 肯定也有三个与之对应回调,通过源码知道 Observable.subscribe 有很多重载方法:

  • public final Subscription subscribe(final Action1<? super T> onNext)
  • public final Subscription subscribe(final Action1<? super T> onNext, final Action1 onError)
  • public final Subscription subscribe(final Action1<? super T> onNext, final Action1 onError, final Action0 onComplete)

第三个重载方法的三个参数分别对应 Subscriber 的三个方法。

总结:Subscriber 是 Observable.create(Observable.OnSubscribe) 参数回调和Observable.subscribe(Action1,[Action1,Action0]) 参数回调的通信桥梁.
需要你注意的是:如果调用了 void onError(Throwable e) 方法,那么 onNext 和 onCompleted 都不会执行。

下面用代码来表示他们之间的关系:

Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            for (int i = 0; i < 5; i++) {
                printLog(tvLogs, "Emit Data:", i + "");
                subscriber.onNext("" + i);//对应 subscribe 方法的第一个参数
                if (condition) {
                    subscriber.onError(Throwable);//对应 subscribe 方法的第二个参数
                }
            }
            subscriber.onCompleted(); //对应 subscribe 方法的第三个参数
        }
    })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribeOn(Schedulers.io())
    .subscribe(new Action1<String>() {
        @Override
        public void call(String s) {
            //showToast(s);
            printLog(tvLogs, "Consume Data:", s);
            //onNext
        }
    }, new Action1<Throwable>() {
        @Override
        public void call(Throwable throwable) {
        	//onError
        }
    }, new Action0() {
        @Override
        public void call() {
        	//onCompleted
        }
    });

3. 总结

  1. 只有当 Observable 被订阅 OnSubscribe 的 call(subscriber) 方法才会被执行

  2. onCompleted 方法里会把 Subscription 取消订阅(unsubscribe)

  3. 如果调用了 void onError(Throwable e) 方法,那么 onNext 和 onCompleted 都不会执行。会在onError 调用之前,把 Subscription 取消注册。

  4. 整个事件流不管是正常结束(onComplete)还是出现了异常(onError),Subscription 都会被取消注册(unsubscribe)。
    但是,由于我们可能执行一些耗时操作,界面又被关闭了,所以还需要把 subscription 取消注册

  5. Subscriber 是 Observable.create(Observable.OnSubscribe) 参数回调和Observable.subscribe(Action1,[Action1,Action0]) 参数回调的通信桥梁.


如果你觉得本文帮助到你,给我个关注和赞呗!

另外,我为 Android 程序员编写了一份:超详细的 Android 程序员所需要的技术栈思维导图

如果有需要可以移步我的 GitHub -> AndroidAll,里面包含了最全的目录和对应知识点链接,帮你扫除 Android 知识点盲区。 由于篇幅原因只展示了 Android 思维导图:
超详细的Android技术栈

  • 15
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chiclaim

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值