框架解析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));
        }
    }

对应流程图

相关推荐
顾北川_野几秒前
Android 手机设备的OEM-unlock解锁 和 adb push文件
android·java
hairenjing11232 分钟前
在 Android 手机上从SD 卡恢复数据的 6 个有效应用程序
android·人工智能·windows·macos·智能手机
小黄人软件28 分钟前
android浏览器源码 可输入地址或关键词搜索 android studio 2024 可开发可改地址
android·ide·android studio
dj15402252031 小时前
group_concat配置影响程序出bug
android·bug
周全全1 小时前
MySQL报错解决:The user specified as a definer (‘root‘@‘%‘) does not exist
android·数据库·mysql
- 羊羊不超越 -2 小时前
App渠道来源追踪方案全面分析(iOS/Android/鸿蒙)
android·ios·harmonyos
wk灬丨2 小时前
Android Kotlin Flow 冷流 热流
android·kotlin·flow
千雅爸爸2 小时前
Android MVVM demo(使用DataBinding,LiveData,Fresco,RecyclerView,Room,ViewModel 完成)
android
晨曦_子画3 小时前
编程语言之战:AI 之后的 Kotlin 与 Java
android·java·开发语言·人工智能·kotlin