框架解析3-RxJava

1、响应式编程

响应式编程特点

  • 事件从起点到终点进行流转,中途不发生中断,但可以对事件进行拦截,并对事件的数据进行转换处理
  • RxJava的使用主要通过各个操作符进行处理
  • 在事件流程过程中,需要对数据进行处理,可通过操作符进行转换
  • RxJava采用链式调用,与传统编码方式相比,一行代码可实现复杂功能,而且可优雅处理多层回调的问题
  • 业务开发过程中,耗时操作在子线程处理,数据结果在主线程展示,RxJava通过操作符完美实现线程切换操作

2、RxJava的使用

2.1、添加依赖

  • rxjava是基本库,rxandroid是扩展在安卓领域使用的库,封装了Android消息机制功能
arduino 复制代码
    implementation 'io.reactivex.rxjava3:rxjava:3.1.5'
    implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'

2.2、RxJava的基本使用

  • create 方法创建被观察者对象(Observable),真实实现类是ObservableCreate,create方法接收参数ObservableOnSubscribe
  • 创建观察者Observer对象
  • 订阅方法subscribe,将观察者与被观察者联系起来,当在ObservableOnSubscribe的subscribe中调用发射emitter的onNext方法对象数据,最终该数据会流转到观察者的onNext方法中进行接收

问题:

  • 为什么在ObservableOnSubscribe的subscribe方法中,调用对象emitter的onNext方法发射数据,最终该数据会流转到观察者的onNext方法?

    kotlin 复制代码
      Observable.create(object : ObservableOnSubscribe<String> {
          override fun subscribe(emitter: ObservableEmitter<String>) { // 发射
              emitter.onNext("11")
              emitter.onNext("12")
              emitter.onNext("13")
    
              emitter.onComplete()
          }
      }).subscribe(object : Observer<String> {
          override fun onSubscribe(d: Disposable) {
              println("RxJava onSubscribe")
          }
    
          override fun onError(e: Throwable) {
              println("RxJava onError:$e")
          }
    
          override fun onComplete() {
              println("RxJava onComplete")
          }
    
          override fun onNext(t: String) {
              println("RxJava onNext:$t")
          }
      })

日志信息:

I/System.out: 复制代码
I/System.out: RxJava onNext:11
I/System.out: RxJava onNext:12
I/System.out: RxJava onNext:13
I/System.out: RxJava onComplete

create方法

  • io.reactivex.rxjava3.core.Observable#create
  • create方法中会传入入参ObservableOnSubscribe对象,可理解为自定义被观察者source,接着创建ObservableCreate实例对象,并将source作为参数传入
  • 接着调用RxJavaPlugins.onAssembly方法,该方法中会判断静态属性onObservableAssembly是否为空,默认为空,所以create方法最终返回的是ObservableCreate对象
  • onObservableAssembly属性可通过RxJavaPlugins.setOnObservableAssembly方法,设置自定义的被观察则对象
typescript 复制代码
    public static <@NonNull T> Observable<T> create(@NonNull ObservableOnSubscribe<T> source) {
        Objects.requireNonNull(source, "source is null");
        return RxJavaPlugins.onAssembly(new ObservableCreate<>(source));
    }
io.reactivex.rxjava3.plugins.RxJavaPlugins#onAssembly(io.reactivex.rxjava3.core.Observable<T>)
    public static <@NonNull T> Observable<T> onAssembly(@NonNull Observable<T> source) {
        Function<? super Observable, ? extends Observable> f = onObservableAssembly;	// f默认为空,直接返回source
        if (f != null) {
            return apply(f, source);
        }
        return source;
    }

    static volatile Function<? super Observable, ? extends Observable> onObservableAssembly;
    public static void setOnObservableAssembly(@Nullable Function<? super Observable, ? extends Observable> onObservableAssembly) {
        if (lockdown) {
            throw new IllegalStateException("Plugins can't be changed anymore");
        }
        RxJavaPlugins.onObservableAssembly = onObservableAssembly;
    }

创建Observer对象

  • 这块没啥好说的,实现Observe接口的匿名内部类
订阅方法subscribe
  • io.reactivex.rxjava3.core.Observable#subscribe(io.reactivex.rxjava3.core.Observer<? super T>)
  • 因为create方法最终返回的是ObservableCreate对象,所以订阅方法调用的实现类也是它,最终会调用ObservableCreate的subscribeActual方法,并将观察者传入其中
less 复制代码
    public final void subscribe(@NonNull Observer<? super T> observer) {
        Objects.requireNonNull(observer, "observer is null");
        try {
            observer = RxJavaPlugins.onSubscribe(this, observer);
            subscribeActual(observer);
        } catch (NullPointerException e) { // NOPMD
            ...
    }

核心方法:实现订阅功能 ObservableCreate.subscribeActual

  • io.reactivex.rxjava3.internal.operators.observable.ObservableCreate#subscribeActual
  • ObservableCreate的属性source,是调用Observable.create方法传入的ObservableOnSubscribe对象
  • 创建发射类CreateEmitter,将观察者对象observer作为参数传入
  • 接着先调用观察则和的onSubscribe方法
  • 最后调用ObservableOnSubscribe的subscribe方法,并将发射类CreateEmitter作为参数传入
  • 这样在ObservableOnSubscribe的subscribe实现方法中,可拿到发射类CreateEmitter调用onNext方法发射数据
  • 而在CreateEmitter中,onNext方法调用的是观察者的onNext方法,这样实现了内部的数据流转
java 复制代码
public final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe<T> source;

    public ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source;
    }

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
		// 创建发射类CreateEmitter,将观察者对象observer作为参数传入
        CreateEmitter<T> parent = new CreateEmitter<>(observer);
		// 先调用观察则和的onSubscribe方法
        observer.onSubscribe(parent);

        try {
			// 最后调用ObservableOnSubscribe的subscribe方法,
            source.subscribe(parent);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }

    static final class CreateEmitter<T>
    extends AtomicReference<Disposable>
    implements ObservableEmitter<T>, Disposable {

        private static final long serialVersionUID = -3434801548987643227L;

        final Observer<? super T> observer;

        CreateEmitter(Observer<? super T> observer) {
            this.observer = observer;
        }

		// 调用发射类CreateEmitter的onNext方法发射数据,最终会调用观察者observer的onNext方法
        @Override
        public void onNext(T t) {
            if (t == null) {
                onError(ExceptionHelper.createNullPointerException("onNext called with a null value."));
                return;
            }
            if (!isDisposed()) {
                observer.onNext(t);
            }
        }

        @Override
        public void onError(Throwable t) {
            if (!tryOnError(t)) {
                RxJavaPlugins.onError(t);
            }
        }

        @Override
        public boolean tryOnError(Throwable t) {
            if (t == null) {
                t = ExceptionHelper.createNullPointerException("onError called with a null Throwable.");
            }
            if (!isDisposed()) {
                try {
                    observer.onError(t);
                } finally {
                    dispose();
                }
                return true;
            }
            return false;
        }

        @Override
        public void onComplete() {
            if (!isDisposed()) {
                try {
                    observer.onComplete();
                } finally {
                    dispose();
                }
            }
        }

        ...
    }
}

画图理解

  • 上述RxJava的使用可以分为三个步骤:创建被观察者,创建观察者和调用订阅方法subscribe
  • 而数据最终从上到下进行流转,内部实现的核心是在被观察者的具体实现类的subscribeActual方法中进行处理
  • RxJava的源码理解之所以绕,主要在他的参与类非常多,只有理清楚各个类组成和他们的相互调用关系,才能更好地理解RxJava框架的设计原理
RxJava基本使用时序图

对应流程图

3、map操作符解析

  • 在业务开发过程中,中途对数据进行处理后再使用这种场景非常常见,在RxJava框架中可通过map操作符进行处理
  • 例子
kotlin 复制代码
        Observable.create(object : ObservableOnSubscribe<Int> {
            override fun subscribe(emitter: ObservableEmitter<Int>) { // 发射
                emitter.onNext(21)
                emitter.onNext(22)
                emitter.onNext(23)

                emitter.onComplete()
            }
        }).map { // int类型数据增加2后,转换成String类型数据
            val t = it + 2
            "result-$t"
        }.subscribe(object : Observer<String> {
            override fun onSubscribe(d: Disposable) {
                println("RxJava onSubscribe")
            }

            override fun onError(e: Throwable) {
                println("RxJava onError:$e")
            }

            override fun onComplete() {
                println("RxJava onComplete")
            }

            override fun onNext(t: String) {
                println("RxJava onNext:$t")
            }
        })

map方法

  • io.reactivex.rxjava3.core.Observable#map
  • 解析,在map方法之前调用了create方法返回的结果是ObservableCreate,所以调用map的实现类是ObservableCreate,
  • 创建ObservableMap对象,this参数就是上面的ObservableCreate对象实例,还有Function数据转换实现类
typescript 复制代码
RxJavaPlugins.onAssembly之前分析过,是作为自定义拦截处理,默认为空
    public final <@NonNull R> Observable<R> map(@NonNull Function<? super T, ? extends R> mapper) {
        Objects.requireNonNull(mapper, "mapper is null");
        return RxJavaPlugins.onAssembly(new ObservableMap<>(this, mapper));
    }

ObservableMap

  • io.reactivex.rxjava3.internal.operators.observable.ObservableMap
  • ObservableMap的构造函数持有的source属性是ObservableCreate对象实例

ObservableMap.subscribeActual

  • subscribeActual方法由ObservableMap的订阅方法触发调用,首先会创建MapObserver,将将观察者对象传入,该观察者就是事件的终点观察者
  • 接着调用 source.subscribe方法,因为该source是ObservableCreate对象实例,调用该方法后接着调用ObservableCreate.subscribeActuat方法,且入参持有的观察者是MapObserver对象实例
  • 接下来调用逻辑就是ObservableCreate.subscribeActuat方法,不同点在于ObservableMap构造函数持有source是ObservableCreate对象实例;而ObservableCreate构造函数持有source是ObservableOnSubscribe对象实例。

得出规律:

  • RxJava的每个操作符方法xxx调用后都会创建一个对应的被观察者(ObservableXxx),除了第一个操作符(create,just等)外,中间的操作符在创建对应观察者ObservableXxx时,都会持有上一个操作符创建的被观察者ObservableXxx(before)
  • 当调用订阅方法subscribe传入最终的观察者时,会调用subscribeActual方法,该方法中会创建自己内部的一个观察者对象(XxxObserver),并调用上一个操作符对应的被观察者的订阅方法,订阅方法都需要传入观察者,此时传入的当前操作符对应被观察者内部创建的观察者(XxxObserver)
  • 按照这个逻辑一直往上调用订阅方法,在当前操作符中,会调用上一个操作符对应被观察者的订阅方法,并传入内部创建的观察者对象(该观察者持有下一个观察者的引用),这样在数据下发的时候,会通过观察者的引用链,不断将数据下发流转

数据流转:

  • ObservableMap中会创建内部的观察者MapObserver,subscribeActual方法中会调用ObservableCreate的订阅方法subscribe,并传入观察者MapObserver对象,
  • 这样在ObservableCreate的subscribeActual方法中,会创建CreateEmitter对象,并持有MapObserver观察者对象
  • 当调用CreateEmitter对象的onNext方法下发数据时,会调用MapObserver.onNext方法,在MapObserver的onNext方法中,会调用mapper.apply(t)方法对数据进行转换,并最终调用重点观察者Observer的onNext方法
scala 复制代码
public final class ObservableMap<T, U> extends AbstractObservableWithUpstream<T, U> {
    final Function<? super T, ? extends U> function;

    public ObservableMap(ObservableSource<T> source, Function<? super T, ? extends U> function) {
        super(source);
        this.function = function;
    }

    @Override
    public void subscribeActual(Observer<? super U> t) {
        source.subscribe(new MapObserver<T, U>(t, function));
    }

    static final class MapObserver<T, U> extends BasicFuseableObserver<T, U> {
        final Function<? super T, ? extends U> mapper;

        MapObserver(Observer<? super U> actual, Function<? super T, ? extends U> mapper) {
            super(actual);
            this.mapper = mapper;
        }

        @Override
        public void onNext(T t) {
            if (done) {
                return;
            }

            if (sourceMode != NONE) {
                downstream.onNext(null);
                return;
            }

            U v;

            try {	// 数据转换处理后,继续往下传递 -》onNext
                v = Objects.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
            } catch (Throwable ex) {
                fail(ex);
                return;
            }
            downstream.onNext(v);
        }

        ...
    }
}

流程图

4、线程切换

  • RxJava中有两个线程切换操作符,subscribeOn和observeOn
  • 其中subscribeOn是给上面的操作部分切换线程操作
  • observeOn是给下面操作部分切换线程
kotlin 复制代码
        Observable.create(object : ObservableOnSubscribe<Int> {
            override fun subscribe(emitter: ObservableEmitter<Int>) { // 发射
                emitter.onNext(31)
                emitter.onNext(32)
                emitter.onNext(33)
            }
        }).subscribeOn(Schedulers.io())    // 给上面切换到子线程
            .observeOn(AndroidSchedulers.mainThread())  // 给下面切换到主线程
            .subscribe(object : Observer<Int> {
                override fun onSubscribe(d: Disposable) {
                    println("onSubscribe")
                }

                override fun onError(e: Throwable) {
                    println("onError:$e")
                }

                override fun onComplete() {
                    println("onComplete")
                }

                override fun onNext(t: Int) {
                    println("onNext:$t")
                }
            })

4.1、subscribeOn

Schedulers.io()

  • io.reactivex.rxjava3.core.Scheduler
  • Schedulers.io()方法最终会返回IoScheduler对象,该对象内部封装了线程池进行线程切换操作
  • Schedulers其他方法调用会获取其他的Scheduler对象,不同的是内部使用了不同的线程池
arduino 复制代码
public final class Schedulers {
    ...
    @NonNull
    static final Scheduler IO;

    static final class IoHolder {
        static final Scheduler DEFAULT = new IoScheduler();
    }

    static final class IOTask implements Supplier<Scheduler> {
        @Override
        public Scheduler get() {
            return IoHolder.DEFAULT;
        }
    }

    static {
        SINGLE = RxJavaPlugins.initSingleScheduler(new SingleTask());

        COMPUTATION = RxJavaPlugins.initComputationScheduler(new ComputationTask());

        IO = RxJavaPlugins.initIoScheduler(new IOTask());

        TRAMPOLINE = TrampolineScheduler.instance();

        NEW_THREAD = RxJavaPlugins.initNewThreadScheduler(new NewThreadTask());
    }
}

subscribeOn

  • io.reactivex.rxjava3.core.Observable#subscribeOn
  • 创建ObservableSubscribeOn被观察者对象
less 复制代码
    public final Observable<T> subscribeOn(@NonNull Scheduler scheduler) {
        Objects.requireNonNull(scheduler, "scheduler is null");
        return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<>(this, scheduler));
    }

ObservableSubscribeOn

  • io.reactivex.rxjava3.internal.operators.observable.ObservableSubscribeOn#ObservableSubscribeOn
  • 当调用ObservableSubscribeOn.subscribeActual方法时,不是直接调用上一层操作符对应的被观察者对象source的订阅方法
  • 而是会创建内部类SubscribeTask(实现了Runnable接口),并交给IoScheduler对象调用scheduleDirect方法,该方法会调用内部的线程池进行执行
  • 这样前面所有的操作符执行的代码都在线程池中
java 复制代码
public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
    final Scheduler scheduler;

    public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
        super(source);
        this.scheduler = scheduler;
    }

    @Override
    public void subscribeActual(final Observer<? super T> observer) {
        final SubscribeOnObserver<T> parent = new SubscribeOnObserver<>(observer);

        observer.onSubscribe(parent);

        parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
    }

    ...

    final class SubscribeTask implements Runnable {
        private final SubscribeOnObserver<T> parent;

        SubscribeTask(SubscribeOnObserver<T> parent) {
            this.parent = parent;
        }

        @Override
        public void run() {
            source.subscribe(parent);
        }
    }
}

EventLoopWorker.schedule

  • IoScheduler的scheduleDirect最终会调用EventLoopWorker的schedule
  • io.reactivex.rxjava3.internal.schedulers.IoScheduler.EventLoopWorker#schedule
  • 并最终交给内部线程池进行执行
  • io.reactivex.rxjava3.internal.schedulers.NewThreadWorker#scheduleActual
less 复制代码
    public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
        
		// 对run任务进行封装
        ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);
        ...
        Future<?> f;
        try {
            if (delayTime <= 0) {
                f = executor.submit((Callable<Object>)sr);	// 调用线程池的submit方法,最终会在子线程中调用SubscribeTask 的run方法
            } else {
                f = executor.schedule((Callable<Object>)sr, delayTime, unit);
            }
            sr.setFuture(f);
        } catch (RejectedExecutionException ex) {
            if (parent != null) {
                parent.remove(sr);
            }
            RxJavaPlugins.onError(ex);
        }
        return sr;
    }

流程图

4.2、observeOn操作符

  • AndroidSchedulers.mainThread()
  • io.reactivex.rxjava3.android.schedulers.AndroidSchedulers#mainThread
  • AndroidSchedulerss是RxAndroid库中的类,调用mainThread方法,会创建一个在主线程中执行任务的Scheduler对象
arduino 复制代码
public final class AndroidSchedulers {

    private static final class MainHolder {
        static final Scheduler DEFAULT = internalFrom(Looper.getMainLooper(), true);
    }

observeOn

  • observeOn方法会创建ObservableObserveOn被观察者对象
  • io.reactivex.rxjava3.core.Observable#observeOn(io.reactivex.rxjava3.core.Scheduler, boolean, int)

ObservableObserveOn.subscribeActual 订阅方法

  • io.reactivex.rxjava3.internal.operators.observable.ObservableObserveOn#subscribeActual
  • subscribeActual方法中会判断当前线程,最终在调用内部观察着的所有方法时,最终也是调用Scheduler的schedule(java.lang.Runnable)方法,最后通过Handler发送callback消息,切换到主线程执行
java 复制代码
public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> {
    final Scheduler scheduler;
    final boolean delayError;
    final int bufferSize;
    public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) {
        super(source);
        this.scheduler = scheduler;
        this.delayError = delayError;
        this.bufferSize = bufferSize;
    }

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        if (scheduler instanceof TrampolineScheduler) {
            source.subscribe(observer);
        } else {
            Scheduler.Worker w = scheduler.createWorker();

            source.subscribe(new ObserveOnObserver<>(observer, w, delayError, bufferSize));
        }
    }

对应流程图

相关推荐
千里马学框架5 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台5 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone5 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc5 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo5 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077005 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼5 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone5 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen5 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone5 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui