RxJava 由浅入深之 Single 串行执行 (一)

RxJava3 Single 简介

本文的代码是在IntellJ环境中测试的,可以直接copy过去运行看看

IntellJ新建Gradle工程,引入依赖

implementation "io.reactivex.rxjava3:rxjava:3.0.0"

在RxJava中,Single可以描述只发送一次事件值的事件,如一次网络请求,它有2个可订阅接口,onSuccess和onError,在任何一个接口触发后会自动解除订阅关系。

//创建Single
Single<String> single = Single.create(emitter -> {
    emitter.onSuccess("ok");
});

//订阅single
single.subscribe(System.out::println);
复制代码

多个Single串行执行

首先创建多个Single

public Single<String> task1() {
    return Single.create((SingleOnSubscribe<String>) em -> {
        em.onSuccess("task-1");
    }).doOnSuccess(s -> {
        System.out.println("发射 ->" + s);
    });
}

public Single<String> task2() {
    return Single.create((SingleOnSubscribe<String>) em -> {
        em.onSuccess("task-2");
    }).doOnSuccess(s -> {
        System.out.println("发射 ->" + s);
    });
}
复制代码

声明多个Single任务

Single<String> single1 = task1();
Single<String> single2 = task2();
复制代码

工作线程,通常直接使用Schedulers.io(),这里用一个线程池,方便在一个线程中打印日志

Executor executor = Executors.newSingleThreadExecutor();
复制代码

场景一:串行执行并接收每个结果

Single.concat(single1, single2)
        .subscribeOn(Schedulers.from(executors))
        .subscribe(s -> {
            System.out.println("接收到->" + s);
        });
复制代码

执行结果:

发射 ->task-1
接收到->task-1
发射 ->task-2
接收到->task-2
复制代码

场景二:根据前一个single的结果,判断是否执行后一个

如先从数据库缓存中读取数据,如果没有再从网络进行请求

Single.concat(single1, single2)
        .subscribeOn(Schedulers.from(executors))
        .takeUntil(s -> {
            return !"".equals(s);
        })
        .filter(s -> {
            return !"".equals(s);
        })
        .subscribe(s -> {
            System.out.println("接收到->" + s);
        });
复制代码

执行结果:

发射 ->task-1
接收到->task-1
复制代码

这里使用takeUntilfilter操作符实现条件判断和过滤不需要的请求结果。

takeUntil在条件返回true时,不再执行下一个Single,并直接返回结果;如果takeUntil条件返回false,其发射的值在filter操作符中被过滤掉,并继续执行下一个Single。

提供默认返回值和异常处理

如果多个single的执行结果都被过滤,则订阅者将收不到任何值,这时可以提供一个默认返回值;

使用single()操作符提供结果为空时的默认返回值

使用onErrorReturn()操作符处理异常

Single.concat(single1, single2)
        .subscribeOn(Schedulers.from(executors))
        .takeUntil(s -> {
            return false;//此处测试全都执行
        })
        .filter(s -> {
            return true;//此处测试全都不满足过滤条件的情况
        })
        .single("default-value")
        .onErrorReturn(Throwable::getLocalizedMessage)
        .subscribe(s -> {
            System.out.println("接收到->" + s);
        });
复制代码

执行结果

发射 ->task-1
发射 ->task-2
接收到->default
复制代码

阻塞的方式实现串行 (不建议使用)

使用blockingGet阻塞工作线程,该方式会使线程阻塞而非挂起,在线程完成前系统其他资源无法使用该线程。

这里很像Kotlin中的协程,但是协程是非阻塞的。

String str1 = single1.subscribeOn(Schedulers.from(executors)).blockingGet();
if (!"success".equals(str1)) {
    single2.subscribeOn(Schedulers.from(executors))
            .subscribe(System.out::println);
}
复制代码

执行结果:

发射 ->task-1
发射 ->task-2
task-2

复制代码

猜你喜欢

转载自juejin.im/post/7119443402046832670
今日推荐