You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RxJava2中如何按依赖关系串行执行列表内的Single任务

问题场景

需要串行执行一组返回相同MyObject类型的RxJava Single任务,且每个任务需要接收上一个任务的输出作为入参。硬编码连续调用flatMap的方式,在任务数量动态变化、或任务以集合形式存储时维护成本很高,而原生concat操作符不支持上下游结果传递,无法满足带依赖传参的串行执行需求。

原有代码示例如下:

// 省略getter/setter
public class MyObject {
    private String a;
    private String b;
    private String c;
    // ...其他字段
}

public Single<MyObject> methodA (MyObject o) {
    return Single.fromCallable(() -> {
        MyObject result;
        if (Objects.nonNull(o)) {
            result = (MyObject) o.clone();
        } else {
            result = new MyObject();
        }
        result.setA("a");
        return result;
    });
}
// methodB、methodC逻辑和methodA类似,分别给对象的b、c字段赋值

原有硬编码串联写法:

Single<MyObject> result = Single.just(new MyObject())
                                .flatMap(x -> methodA(x))
                                .flatMap(x -> methodB(x));

实现方案

首先需要纠正一个认知误区:不要尝试直接用List<Single<MyObject>>实现这个需求。Single在创建时就已经捕获了它需要的入参,没有入口动态传入上一步的执行结果,你需要存储的是Function<MyObject, SingleSource<MyObject>>类型的任务函数——也就是接收上一步结果、返回对应Single任务的方法引用(比如this::methodA、this::methodB都属于这个类型),才能实现动态传参的串行执行。

方案1:封装通用工具方法(最直观、性能最好)

直接抽一个通用的链式拼接工具,循环组装flatMap调用,逻辑简单无额外依赖:

public class RxChainUtil {
    /**
     * 串行执行带参数传递的Single任务链
     * @param initial 初始入参对象
     * @param tasks 任务函数列表,每个函数接收上一步结果,返回新的Single任务
     * @return 串联完成后的最终Single结果
     * @param <T> 任务处理的对象类型
     */
    public static <T> Single<T> chainSingle(T initial, List<Function<T, SingleSource<T>>> tasks) {
        Single<T> current = Single.just(initial);
        for (Function<T, SingleSource<T>> task : tasks) {
            current = current.flatMap(task);
        }
        return current;
    }
}

调用方式非常简洁,后续新增任务只需要往列表里加元素即可,不需要修改链式调用代码:

// 组装任务列表
List<Function<MyObject, SingleSource<MyObject>>> taskList = Arrays.asList(
        this::methodA,
        this::methodB,
        this::methodC
);
// 直接执行拿到最终结果
Single<MyObject> result = RxChainUtil.chainSingle(new MyObject(), taskList);

方案2:用reduce操作符函数式串联

如果不想写循环,也可以用流的reduce操作符动态拼接flatMap链,完全非阻塞:

List<Function<MyObject, SingleSource<MyObject>>> taskList = Arrays.asList(
        this::methodA,
        this::methodB,
        this::methodC
);

Single<MyObject> result = Single.just(new MyObject())
        .flatMapPublisher(initialObj -> Flowable.fromIterable(taskList)
                .reduce(
                        Single.just(initialObj),
                        (prevSingle, task) -> prevSingle.flatMap(task)
                )
                .toFlowable()
        )
        .singleOrError()
        .flatMap(s -> s);

内容的提问来源于stack exchange,提问作者chavalife17

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 04:39:21