RxJava/RxAndroid的基本使用方法(一)

文章目录

  • 一、什么是RxJava
  • 二、使用前的准备
    • 1、导入相关依赖
    • 2、字段含意
    • 3、Upstream/Downstream——上/下游
    • 4、BackPressure
    • 5、BackPressure策略
    • 6、“热” and “冷” Observables
    • 7、 基类
    • 8、事件调度器
    • 9、操作符是什么?
    • 10 、Consumer和 Observer的区别
  • 三、RxJava的简单用法
    • 1、Observable——Observer
    • 2、Flowable——Subscriber
    • 3、Completable——CompletableObserver
    • 4、Maybe——MaybeObserver
    • 5、Single——SingleObserver
      • **Single的操作符**
      • 5.1、just: 创建一个发射单一数据项的 `Single`
      • 5.2、error:创建一个发射错误通知的 `Single`
      • 5.3 map: 对 `Single` 中的数据进行转换
      • 5.4 flatMap: 将一个 `Single` 转换为另一个 `Single`
      • 5.5 zip:将多个 `Single` 组合成一个新的 `Single`,并在它们都成功时触发。
      • 5.6 Single的转化模式
        • 5.6.1 将 Single 转换为 Observable——single.toObservable
        • 5.6.2 将 Observable 转换为 Single
        • 5.6.3 将 Single转换为 Completable——single.ignoreElement
        • 5.6.4 将 Single转换为 Maybe——single.toMaybe
  • 四、事件调度器释放事件
  • 五、Scheduler——调度者
  • 关于RxJava/RxAndroid的全部文章

一、什么是RxJava

ReactiveX 是一个使用可观察序列编写异步和基于事件的程序的库。它扩展了观察者模式以支持数据和/或事件序列,并添加了运算符,允许以声明方式将序列组合在一起,同时抽象出对低级线程、同步、线程安全、并发数据结构和非线程等问题的关注和阻塞 I/O。

官网链接:ReactiveX

什么是响应式编程?

响应式编程是一种编程范式,旨在处理异步数据流和事件驱动的编程。它着重于数据流和变化的处理,使得在异步和事件驱动环境中更容易构建可维护可伸缩高响应的应用程序。

  1. 数据流: 响应式编程关注数据流,将数据视为一系列事件或变化。
  2. 响应性: 响应式编程强调应用程序对事件和数据的即时响应能力。它允许应用程序根据数据流中的事件来触发操作,而不是等待数据的拉取或轮询。
  3. 观察者模式: 响应式编程经常使用观察者模式,其中存在一个可观察对象(Observable)和一个或多个观察者(Observer)。可观察对象发出事件,观察者订阅并对这些事件作出反应。
  4. 流式操作: 响应式编程提供了一组丰富的操作符,用于处理、过滤、转换和合并数据流。这些操作符允许开发人员以声明性方式构建数据流处理管道。
  5. 背压处理: 响应式编程处理异步数据流时,考虑了背压问题,即生产者产生数据的速度大于消费者处理数据的速度。它提供了一些机制来处理背压,如缓冲、丢弃、错误处理等。
  6. 异步性: 在响应式编程中,大部分操作都是异步执行的,这有助于避免应用程序的阻塞,提高性能和响应能力。

RxJava的观察者模式

RxJava有四个基本概念:Observer(观察者),Observable(被观察者),subscribe(订阅),事件

ObserverObservable通过subscribe()实现订阅关系,从而Observable可以在需要的时候发出事件通知Observer。

  • Observer: 观察者,它决定事件发生时有怎么样的行为;
  • Observable: 被观察者,它决定什么时候出发事件以及触发什么样的事件;
  • subscribe:订阅,将Observer和Observable关联起来

二、使用前的准备

1、导入相关依赖

最新依赖地址:Github-RxJava/RxAndroid

    implementation "io.reactivex.rxjava3:rxjava:3.1.8"
    implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'

2、字段含意

Reactive:根据上下文一般翻译为反应式、响应式。

Iterable :可迭代对象,支持以迭代器的形式遍历。

Observable: 可观察对象,在Rx中定义为更强大的Iterable,在观察者模式中是被观察的对象,一旦数据产生或发生变化,会通过某种方式通知观察者或订阅者。

Observer :观察者对象,监听Observable发射的数据并做出响应,Subscriber是它的一个特殊实现。

emit: 含义是Observable在数据产生或变化时发送通知给Observer,调用Observer对应的方法,翻译为发射

items: 在Rx里是指Observable发射的数据项

3、Upstream/Downstream——上/下游

在响应式编程中,"上游"和"下游"通常用于描述数据流的生产者和消费者之间的关系。

  1. 上游(Upstream):上游是数据流的生产者,它生成和发出数据项。上游通常是源(例如,传感器、数据库查询、文件读取等),它们生成数据并将其传递给下游。
  2. 下游(Downstream):下游是数据流的消费者,它接收和处理来自上游的数据项。下游可以执行各种操作,如过滤、映射、转换、订阅等。它们通常是应用程序中的组件,用于处理和响应来自上游的数据。

在响应式编程中,数据通过流动的方式从上游传递到下游,这是一种异步的、非阻塞的方式。

上游和下游之间的通信通常是通过观察者模式或发布-订阅模式进行的,以实现数据的异步传递和处理。这种方式使得可以构建高效的、响应式的应用程序,能够处理异步数据流。

4、BackPressure

BackPressure直译为:背压,也叫做反压。

背压(Backpressure)是指在异步编程中,当生产者(Producer)生成数据的速度快于消费者(Consumer)处理数据的速度时,数据压力会在系统中积累,可能导致一些问题,如内存溢出或性能下降。

在RxJava中也就是被观察者(Observable)发送事件的速度快于观察者(Observer)的速度

背压问题通常出现在处理数据流的情况下,其中数据生产速度不受消费速度的限制。

5、BackPressure策略

image-20231106174727841

  1. MISSING:缺省设置,不做任何操作,而不进行任何缓冲或丢弃。
  2. ERROR: 当订阅者无法处理来自发布者的数据时,会引发 MissingBackpressureException 异常,表示出现了背压问题。
  3. BUFFER:当订阅者无法处理来自发布者的数据时,数据会被缓冲在内存中,直到订阅者可以处理它们。
  4. DROP: 把存不下的事件丢弃。
  5. LATEST:只保留最新的数据项,丢弃之前的数据。

6、“热” and “冷” Observables

Observable 何时开始发出其items?这取决于Observable。一个“热”Observable 可能会在创建后立即开始发射items,因此任何后续订阅该 Observable 的观察者都可能会开始观察中间某个位置的序列。另一方面,“冷”Observable 会等到观察者订阅它之后才开始发射items,因此这个观察者可以确保会收到整个数据序列。

7、 基类

RxJava 3 中的基类相比RxJava 2 没啥改变,主要有以下几个基类:

  • io.reactivex.Observable:发送0个/N个的数据,不支持BackPressure,有onNextonComplete

  • io.reactivex.Flowable:发送0个/N个的数据,支持Reactive-Streams和支持BackPressure,有onNextonComplete

  • io.reactivex.Single:只能发送单个数据或者一个错误,有onSuccess

  • io.reactivex.Completable:没有发送任何数据,但只处理 onComplete 和 onError 事件。有onComplete

  • io.reactivex.Maybe:能够发射0或者1个数据,要么成功,要么失败。有onSuccessonComplete

8、事件调度器

RxJava事件发出去并不是置之不顾,要有合理的管理者来管理它们,在合适的时机要进行释放事件,这样才不会导致内存泄漏,这里的管理者我们称为事件调度器CompositeDisposable

9、操作符是什么?

RxJava 提供了各种操作符,用于对观察序列进行转换、过滤、组合和处理。这些操作符可帮助你更灵活地处理异步数据流。

常见的操作符有:create、just、error、map、flatMap。在后面介绍Single的时候会简单的介绍。更多关于操作符的使用在下一篇博客RxJava的操作符使用(二)中详细介绍,这里简单了解概念就行了。

10 、Consumer和 Observer的区别

  • Consumer: 主要用于处理从 Observable 发出的数据项,它接受一个参数并执行操作,通常用于处理 onNext 事件。
  • Observer: 用于处理完整的事件序列,包括 onNext、onError、onComplete 等事件。Observer 接口包括多个回调方法,可以用于处理不同类型的事件。

三、RxJava的简单用法

**RxJava以观察者模式为骨架,**有两种常见的观察者模式:

  • Observable(被观察者)/Observer(观察者)
  • Flowable(被观察者)/Subscriber(观察者)

image-20231106181029150

使用流程:

  1. 创建被观察者
  2. 创建观察者
  3. 订阅被观察者
  4. 取消订阅(这一步可以省略)

1、Observable——Observer

一般用法:

//创建被观察者/事件源
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Throwable {
        emitter.onNext("a");
        emitter.onNext("b");
        emitter.onNext("c");
        emitter.onComplete();
    }
});

//创建观察者
Observer observer = new Observer<String>() {

    @Override
    public void onSubscribe(@NonNull Disposable d) {
        Log.e("TAG", "onSubscribe == 订阅");
    }

    @Override
    public void onNext(@NonNull String s) {
        Log.e("TAG", "onNext == " + s);
    }

    @Override
    public void onError(@NonNull Throwable e) {
        Log.e("TAG", "onError == " + e.toString());
    }

    @Override
    public void onComplete() {
        Log.e("TAG", "onComplete");
    }
};

//订阅(观察者监视被观察着)
observable.subscribe(observer);

//取消订阅
observable.distinct();

image-20231106181404793

这种观察者模型不支持背压:当被观察者快速发送大量数据时,下游不会做其他处理,即使数据大量堆积,调用链也不会报MissingBackpressureException

消耗内存过大只会OOM。所以,当我们使用Observable——Observer的时候,我们需要考虑的是,数据量是不是很大(官方给出以1000个事件为分界线作为参考)。

并且观察者具有多个重载方法:

    //观察者不对被观察者发送的事件做出响应(但是被观察者还可以继续发送事件)
    public final Disposable subscribe()
 
    //观察者对被观察者发送的任何事件都做出响应
    public final void subscribe(Observer<? super T> observer)
 
    //表示观察者只对被观察者发送的Next事件做出响应
    public final Disposable subscribe(Consumer<? super T> onNext)
 
    //表示观察者只对被观察者发送的Next & Error事件做出响应
    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError)
 
    //表示观察者只对被观察者发送的Next & Error & Complete事件做出响应
    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
                                      Action onComplete)
 
    //表示观察者只对被观察者发送的Next & Error & Complete & onSubscribe事件做出响应
    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
                                      Action onComplete, Consumer<? super Disposable> onSubscribe)

2、Flowable——Subscriber

Flowable<Integer> flowable = Flowable.create(new FlowableOnSubscribe<Integer>() {
    @Override
    public void subscribe(@NonNull FlowableEmitter<Integer> emitter) throws Throwable {
        emitter.onNext(1);
        emitter.onNext(2);
        emitter.onNext(3);
        emitter.onNext(4);
        emitter.onComplete();
    }
}, BackpressureStrategy.BUFFER);

Subscriber<Integer> subscriber = new Subscriber<Integer>() {

    Subscription sub;

    @Override
    public void onSubscribe(Subscription s) {
        Log.w("TAG", "onsubscribe start");
        sub = s;
        s.request(1);
        Log.w("TAG", "onsubscribe end");
    }

    @Override
    public void onNext(Integer integer) {
        Log.e("TAG", "onNext == " + integer);
        sub.request(1);
    }

    @Override
    public void onError(Throwable t) {
        t.printStackTrace();
    }

    @Override
    public void onComplete() {
        Log.e("TAG", "onComplete");
    }
};


flowable.subscribe(subscriber);

image-20231106184629182

Flowable是支持背压的,也就是说,一般而言,上游的被观察者会响应下游观察者的数据请求,下游调用request(n)来告诉上游发送多少个数据。这样避免了大量数据堆积在调用链上,使内存一直处于较低水平。

Flowable使用create()创建时,必须指定BackPressure策略。

注意

尽可能确保在request()之前已经完成了所有的初始化工作,否则就有空指针的风险。

3、Completable——CompletableObserver

它只有onComplete和onError两个事件

//被观察者
Completable completable = Completable.create(new CompletableOnSubscribe() {
    @Override
    public void subscribe(@NonNull CompletableEmitter emitter) throws Throwable {
        emitter.onComplete();
    }
});

//订阅观察者
completable.subscribe(new CompletableObserver() {
    @Override
    public void onSubscribe(@NonNull Disposable d) {

    }

    @Override
    public void onComplete() {
        Log.e("TAG","onComplete");
    }

    @Override
    public void onError(@NonNull Throwable e) {

    }
});

image-20231106210536185

要转换成其他类型的被观察者,也是可以使用toFlowable()toObservable()等方法去转换。

4、Maybe——MaybeObserver

如果你的需求是可能发送一个数据或者不会发送任何数据,这时候你就需要Maybe,它类似于SingleCompletable的混合体。

        //被观察者
        Maybe<String> maybe = Maybe.create(new MaybeOnSubscribe<String>() {
            @Override
            public void subscribe(@NonNull MaybeEmitter<String> emitter) throws Throwable {
                emitter.onSuccess("have Data"); //发送一个数据的情况
//                emitter.onComplete();   //不发送数据的情况
            }
        });

        //订阅观察者
        maybe.subscribe(new MaybeObserver<String>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {

            }

            @Override
            public void onSuccess(@NonNull String s) {
                Log.e("TAG",s);
            }

            @Override
            public void onError(@NonNull Throwable e) {

            }

            @Override
            public void onComplete() {
                Log.e("TAG","无数据");
            }
        });

image-20231106211427552

5、Single——SingleObserver

Single类似于Observable,不同的是,它总是只发射一个值,而不是发射一系列的值(并不存在MissingBackpressureException问题),所以当你使用一个单一连续事件流,这样可以使用Single。

Single观察者只包含两个事件,一个是正常处理成功的onSuccess,另一个是处理失败的onError。

Single.create

Single<String> stringSingle = Single.create(new SingleOnSubscribe<String>() {
    @Override
    public void subscribe(@NonNull SingleEmitter<String> emitter) throws Throwable {
        emitter.onSuccess("success1");
        emitter.onSuccess("success2");
    }
});


stringSingle.subscribe(new SingleObserver<String>() {
    @Override
    public void onSubscribe(@NonNull Disposable d) {
        Log.e("TAG", "onSubscribe: "+d);
    }

    @Override
    public void onSuccess(@NonNull String s) {
        Log.e("TAG", "onSuccess: "+s);
    }

    @Override
    public void onError(@NonNull Throwable e) {
        e.printStackTrace();
    }
});

image-20231106184706201

可以看见数据只会发送一次,Single只会调用这两个方法中的一个,而且只会调用一次,调用了任何一个方法之后,订阅关系终止

Single 类型的操作符用于处理这些单一的数据项或错误。

Single的操作符

更多关于操作符的使用在下一篇博客这里简单了解概念就行了。

操作符返回值说明
composeSingle创建一个自定义的操作符
concat and concatWithObservable连接多个 Single 和 Observable 发射的数据
createSingle调用观察者的 create 方法创建一个 Single
errorSingle返回一个立即给订阅者发射错误通知的 Single
flatMapSingle返回一个 Single,它发射对原 Single 的数据执行 flatMap 操作后的结果
flatMapObservableObservable返回一个 Observable,它发射对原 Single 的数据执行 flatMap 操作后的结果
fromSingle将 Future 转换成 Single
justSingle返回一个发射一个指定值的 Single
mapSingle返回一个 Single,它发射对原 Single 的数据执行 map 操作后的结果
mergeSingle将一个 Single(它发射的数据是另一个 Single,假设为 B)转换成另一个 Single(它发射来自另一个 Single(B) 的数据)
merge and mergeWithObservable合并发射来自多个 Single 的数据
observeOnSingle指示 Single 在指定的调度程序上调用订阅者的方法
onErrorReturnSingle将一个发射错误通知的 Single 转换成一个发射指定数据项的 Single
subscribeOnSingle指示 Single 在指定的调度程序上执行操作
timeoutSingle它给原有的 Single 添加超时控制,如果超时了就发射一个错误通知
toSingleSingle将一个发射单个值的 Observable 转换为一个 Single
zip and zipWithSingle将多个 Single 转换为一个,后者发射的数据是对前者应用一个函数后的结果

用法示例:

5.1、just: 创建一个发射单一数据项的 Single

Single.just

Single<Integer> single = Single.just(42);

5.2、error:创建一个发射错误通知的 Single

Single.error

Single<String> single = Single.error(new RuntimeException("Something went wrong"));

5.3 map: 对 Single 中的数据进行转换

Single.map

        Single<Integer> source = Single.just(5);
        Single<String> mapped = source.map(new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) throws Throwable {
                return "integer : "+integer;
            }
        });

这意味着原始整数数据 5 经过映射操作转变为了字符串数据,带有特定的前缀。

这种操作在响应式编程中非常有用,因为它允许你对数据进行转换和处理,而不改变数据流的类型。你可以将原始数据映射为需要的格式,以满足应用程序的需求。

5.4 flatMap: 将一个 Single 转换为另一个 Single

Single.map

        Single<Integer> source = Single.just(5);
        Single<String> mapped = source.flatMap(new Function<Integer, SingleSource<? extends String>>() {
            @Override
            public SingleSource<? extends String> apply(Integer integer) throws Throwable {
                return Single.just("Return : "+integer);
            }
        });

5.5 zip:将多个 Single 组合成一个新的 Single,并在它们都成功时触发。

Single.zip

Single<Integer> source = Single.just(5);
Single<String> mapped = source.flatMap(new Function<Integer, SingleSource<? extends String>>() {
    @Override
    public SingleSource<? extends String> apply(Integer integer) throws Throwable {
        return Single.just("Return : " + integer);
    }
});

Single single = Single.zip(source, mapped, new BiFunction<Integer, String, Object>() {
    @Override
    public Object apply(Integer integer, String s) throws Throwable {
        return "Return : " + integer + s;
    }
});

5.6 Single的转化模式

5.6.1 将 Single 转换为 Observable——single.toObservable
Single<Integer> source = Single.just(5);

// 将 Single 转换为 Observable
Observable<Integer> observable = source.toObservable();

// 现在你可以将 Single 的结果集成到 Observable 中
observable.subscribe(
    value -> Log.e("TAG","Received value: " + value),
    error -> Log.e("TAG","Error: " + error),
    () -> Log.e("TAG","Completed")
);
5.6.2 将 Observable 转换为 Single
Observable<Integer> observable = Observable.just(1, 2, 3, 4, 5);

// 将 Observable 转换为 Single,只发射第一个数据项或错误
Single<Integer> single = observable.first(0);

// 现在你可以将 Observable 的结果集成到 Single 中
single.subscribe(
    value -> System.out.println("Received value: " + value),
    error -> System.err.println("Error: " + error)
);

5.6.3 将 Single转换为 Completable——single.ignoreElement
Single<Integer> single = Single.just(42);

// 将 Single 转换为 Completable,忽略结果,只关注完成或错误
Completable completable = single.ignoreElement();

// 现在你可以使用 Completable 来执行某些操作
completable.subscribe(
    () -> System.out.println("Completed"),
    error -> System.err.println("Error: " + error)
);
5.6.4 将 Single转换为 Maybe——single.toMaybe
Single<Integer> single = Single.just(42);

// 将 Single 转换为 Maybe,考虑成功结果、错误或没有结果
Maybe<Integer> maybe = single.toMaybe();

// 现在你可以使用 Maybe 来处理这三种情况
maybe.subscribe(
    value -> System.out.println("Received value: " + value),
    error -> System.err.println("Error: " + error),
    () -> System.out.println("No result")
);

四、事件调度器释放事件

  1. Disposable:

    • Disposable 是 RxJava 的通用接口,用于表示订阅关系。
    • 它与所有的 RxJava 数据类型都相关,包括 ObservableFlowableSingleCompletableMaybe
    • 当你订阅一个数据流时,RxJava 会返回一个 Disposable 对象,你可以使用它来取消订阅或检查订阅状态。
       // 创建一个简单的 Observable,发射一些数据
    	Observable stringObservable = Observable.create(new ObservableOnSubscribe<String>() {
                @Override
                public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Throwable {
                    emitter.onNext("Xiyou");
                    emitter.onNext("3G");
                    emitter.onNext("Android");
                    emitter.onComplete();
                }
            });
    
    // 订阅 Observable 并获取 Disposable 对象
            Disposable disposable = stringObservable.subscribe(
                    value -> Log.e("TAG", value.toString()),
                    error -> Log.e("TAG", "ERROR" + error),
                    () -> Log.e("TAG", "Completed")
            );
    
            disposable.dispose();   //在需要的时候取消订阅
    
  2. CompositeDisposable:

    • CompositeDisposableDisposable 接口的实现。
    • 它特别用于管理多个订阅关系,以便一次性取消多个订阅。
    • CompositeDisposable 可以添加多个 Disposable 对象,并在需要时一次性取消它们。
    • 这在管理多个订阅关系时非常有用,例如在 Android 中管理多个异步任务的订阅。
            //创建一个简单的 Observable,发射一些数据
            Observable stringObservable = Observable.create(new ObservableOnSubscribe<String>() {
                @Override
                public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Throwable {
                    emitter.onNext("Xiyou");
                    emitter.onNext("3G");
                    emitter.onNext("Android");
                    emitter.onComplete();
                }
            });
    
            // 创建一个 CompositeDisposable 来管理订阅关系
            CompositeDisposable compositeDisposable = new CompositeDisposable();
    
            // 订阅 Observable 并获取 Disposable 对象
            Disposable disposable = stringObservable.subscribe(
                    value -> Log.e("TAG", value.toString()),
                    error -> Log.e("TAG", "ERROR" + error),
                    () -> Log.e("TAG", "Completed")
            );
    
            // 将 Disposable 对象添加到 CompositeDisposable 中
            compositeDisposable.add(disposable);
    
            // 在不再需要订阅关系时,可以取消它们
            // compositeDisposable.clear(); // 取消所有订阅
            // 或者单独取消某个订阅
            // disposable.dispose();
    
            // 在不再需要 CompositeDisposable 时,清理它
            compositeDisposable.dispose();
    

    CompositeDisposable提供的方法中,都是对事件的管理

    • dispose():释放所有事件
    • clear():释放所有事件,实现同dispose()
    • add():增加某个事件
    • addAll():增加所有事件
    • remove():移除某个事件并释放
    • delete():移除某个事件

五、Scheduler——调度者

在RxJava默认规则中,事件的发出和消费都是在同一个线程中发生的,那么上面的这些例子来说,就是一个同步的观察者模式。

在RxJava中Scheduler(调度器)相当于线程控制器,RxJava通过Scheduler来指定那一部分代码执行在哪一个线程。我们来看看简单的例子:

 Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
                    @Override
                    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                        emitter.onNext("RxJava:e.onNext== 第一次");
                        emitter.onComplete();
                        Log.d("TAG", "subscribe()线程==" + Thread.currentThread().getId());
                    }
                }).subscribeOn(Schedulers.io())//指定被观察者subscribe()(发射事件的线程)在IO线程()
                .observeOn(AndroidSchedulers.mainThread());//指定观察者接收响应事件的线程在主线程


        observable.subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {

            }

            @Override
            public void onNext(@NonNull String s) {
                // 接收到数据时的回调,s 是传递的数据
                Log.d("TAG", "Received data: " + s);
                Log.d("TAG", "onNext()线程==" + Thread.currentThread().getId());
            }

            @Override
            public void onError(@NonNull Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
  • subscribeOn():用于指定Observable被观察者subscribe()时所发生的线程,即指定发生事件的线程
  • observeOn():指定Observer观察者接收&响应事件的线程,即观察者接收事件的线程

注意:多次指定发射事件的线程只有第一次指定有效,也就是说多次调用subscribeOn()只有第一次有效,其余的会被忽略;但是多次指定订阅者接收事件的线程是可以的,也就是说每observeOn()一次,接收事件的线程就会切换一次。

  • Schedulers.io():代表IO操作的线程,通常用于网络、读写文件等IO密集型的操作。行为模式和new Thread()差不多,只是IO的内部是一个无上限的线程池,可重用空闲的线程,更高效(不要把计算工作放在IO内,可以避免创建不必要的线程)
  • AndroidSchedulers.mainThread():Android的主线程;用于更新UI
  • Schedulers.newThread():总是启用新线程,并在新线程中执行操作;多用于耗时操作
  • Schedulers.computation(): 代表CPU计算密集型的操作,即不会被IO等操作限制性能的操作。

关于RxJava/RxAndroid的全部文章

RxJava/RxAndroid的基本使用方法(一)

RxJava的操作符使用(二)


参考文档:

官方文档:reactivex

RxJava3 Wiki:Home · ReactiveX/RxJava Wiki · GitHub

RxJava3官方github:What’s different in 3.0 · ReactiveX/RxJava Wiki · GitHub

RxJava2 只看这一篇文章就够了–玉刚说

RxJava2最全面、最详细的讲解–苏火火丶

关于背压(Backpressure)的介绍:关于RxJava最友好的文章——背压(Backpressure)

RXJava3+OKHTTP3+Retrofit2(观察者设计模式)讲解+实战

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/125840.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

已解决:Python Error: IndentationError: expected an indented block 问题

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页: &#x1f405;&#x1f43e;猫头虎的博客&#x1f390;《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f996…

C# OpenCvSharp 玉米粒计数

效果 项目 代码 using OpenCvSharp; using System; using System.Drawing; using System.Text; using System.Windows.Forms;namespace OpenCvSharp_Demo {public partial class frmMain : Form{public frmMain(){InitializeComponent();}string fileFilter "*.*|*.bmp;…

OpenGL_Learn08(坐标系统与3D空间)

目录 1. 概述 2. 局部空间 3. 世界空间 4. 观察空间 5. 剪裁空间 6. 初入3D 7. 3D旋转 8. 多个正方体 9. 观察视角 1. 概述 OpenGL希望在每次顶点着色器运行后&#xff0c;我们可见的所有顶点都为标准化设备坐标(Normalized Device Coordinate, NDC)。也就是说&#x…

C++跨模块传递CRT引发问题

SDK新增加了一个接口&#xff0c;参数使用std::vector<Class>&&#xff0c;传给dll函数中填充数值&#xff0c;然后应用层拿到这个vector出现了崩溃 越界等问题&#xff0c;调了很久&#xff0c;之前知道这个问题&#xff0c;没有想起来&#xff0c;耽误了许多时间。…

用Python的requests库来模拟爬取地图商铺信息

由于谷歌地图抓取商铺信息涉及到API使用和反爬虫策略&#xff0c;直接爬取可能会遇到限制。但是&#xff0c;我们可以使用Python的requests库来模拟爬取某个网页&#xff0c;然后通过正则表达式或其他文本处理方法来提取商铺信息。以下是一个简单的示例&#xff1a; # 导入requ…

uniapp+uview2.0+vuex实现自定义tabbar组件

效果图 1.在components文件夹中新建MyTabbar组件 2.组件代码 <template><view class"myTabbarBox" :style"{ backgroundColor: backgroundColor }"><u-tabbar :placeholder"true" zIndex"0" :value"MyTabbarS…

网页分析和xml.etree库

源代码&#xff1a; Lib/xml/etree/ElementTree.py 该xml.etree.ElementTree模块实现了一个简单高效的 API&#xff0c;用于解析和创建 XML 数据。 一、说明 这是一个简短的使用教程xml.etree.ElementTree&#xff08;ET简而言之&#xff09;。目标是演示该模块的一些构建块和基…

基于FPGA的模板匹配红外目标跟踪算法设计

为什么要写这篇文章 我写这篇文章的原因是一天在B站看到了一个大神发的视频是关于跟踪一个无人机的&#xff0c;看到作者跟网友的回复说是用的图像匹配算法&#xff0c;我就在网上搜索相关资料&#xff0c;最终找到一篇文献。文献中对该算法的评价很高&#xff0c;满足制导系统…

为你摘星辰

欢迎来到程序小院 为你摘星辰 玩法&#xff1a;鼠标控制人物方向&#xff0c;点击鼠标键上升人物&#xff0c;经过⭐️⭐️吃掉获得分数&#xff0c;共三次生命&#xff0c;碰到红色障碍物减去一次生命&#xff0c; 人物掉落底部游戏结束&#xff0c;看你获得多少分^^。开始游…

排序算法的空间复杂度和时间复杂度

一、排序算法的时间复杂度和空间复杂度 排序算法 平均时间复杂度 最坏时间复杂度 最好时间复杂度 空间复杂度 稳定性 冒泡排序 O(n) O(n) O(n) O(1) 稳定 直接选择排序 O(n) O(n) O(n) O(1) 不稳定 直接插入排序 O(n) O(n) O(n) O(1) 稳定 快速排序 O(n…

ChatGPT付费创作系统V2.4.9独立版 +WEB端+ H5端 + 小程序端系统测试安装教程

播资源提供的GPT付费体验系统最新版系统是一款基于ThinkPHP框架开发的AI问答小程序&#xff0c;是基于国外很火的ChatGPT进行开发的Ai智能问答小程序。当前全民热议ChatGPT&#xff0c;流量超级大&#xff0c;引流不要太简单&#xff01;一键下单即可拥有自己的GPT&#xff01;…

【TASKING】如何提高编译器的编译速度

文章目录 前言一、How to Improve the compilation speed.1.1、Cache generated code to improve the compilation speed1.2 Influencing the Build TimeSFR File&#xff08;勾了可能会报错&#xff0c;好像得配合include一起用&#xff0c;暂未研究清除&#xff0c;仅供参考&…

死亡游戏:密室互猜硬币规则及其破解方法

今天听到一个有点小恐怖的死亡游戏 规则是 将你和最好的朋友 分别关进两个不同的房间 要关 100天 在被关的时间里 你们无法进行任何的沟通 每一天 会有一个人在你和朋友的房间分别抛一次硬币 你们需要去猜对方硬币的正反面 只需要一个人猜对了 则 相安无事 如果两个人都猜错了…

android手机平板拓展电脑音频

&#xff08;1&#xff09;首先确保电脑上有声卡&#xff0c;就是电脑右下角小喇叭能调音量&#xff0c;不管电脑会不会响&#xff0c;如果小喇叭标记了个错误&#xff0c;说明没有声卡&#xff0c;安装图上的虚拟声卡软件。 &#xff08;2&#xff09;图上第一个PC免安装及局…

图像二值化阈值调整——Triangle算法,Maxentropy方法

一. Triangle方法 算法描述&#xff1a;三角法求分割阈值最早见于Zack的论文《Automatic measurement of sister chromatid exchange frequency》主要是用于染色体的研究&#xff0c;该方法是使用直方图数据&#xff0c;基于纯几何方法来寻找最佳阈值&#xff0c;它的成立条件…

Qt 项目实战 | 音乐播放器

Qt 项目实战 | 音乐播放器 Qt 项目实战 | 音乐播放器播放器整体架构创建播放器主界面媒体对象状态实现播放列表实现桌面歌词添加系统托盘图标 资源下载 官方博客&#xff1a;https://www.yafeilinux.com/ Qt开源社区&#xff1a;https://www.qter.org/ 参考书&#xff1a;《Q…

怎么建模HEC-RAS【案例-利用HEC-RAS分析河道建筑对洪水管控的作用】 洪水计算、堤防及岸坡稳定计算、冲淤分析、壅水计算、冲刷计算、水工构筑物建模

背景介绍 人口数量的增长、不合理的区域规划和无计划的工程实践&#xff0c;让洪水对于人类而言变得极具风险。 为了最大程度地减少洪水造成的损害&#xff0c;采取管控措施往往需要在初期执行&#xff0c;为了研究这些管控措施&#xff0c;需要确定河段桥梁和作为调节的水利设…

[工业自动化-7]:西门子S7-15xxx编程 - PLC主站 - 电源模块

目录 前言&#xff1a; 一、主站电源PM VS PS 1.1 主站PM电源模块(PM) 1.2 主站PS电源模块 1.3 PM/PS电源模块区别 1.4 如何选择PM/PS电源 1.5 什么时候必须使用PM模块 1.6 什么时候必须使用PS模块 二、背板总线 三、电源模块的安装 前言&#xff1a; 一、主站电源PM…

电商项目之Java8函数式接口落地实践

文章目录 1 问题背景2 前言3 多处重复的重试机制代码4 优化后的代码5 进一步优化 1 问题背景 在电商场景中&#xff0c;会调用很多第三方的云服务&#xff0c;比如发送邮件、发起支付、发送验证码等等。由于网络存在抖动&#xff0c;有时候发起调用后会拿到500的状态码&#xf…

jquery的项目,html页面使用vue3 +element Plus

vue3&#xff0c;element引入 <script src"../vue3.3.8/vue.global.js"></script> <link rel"stylesheet" href"js/elementPlus/index.css"> <script src"js/elementPlus/index.full.js"></script>…
最新文章