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

RxJava嵌套链式调用行为异常 无法将嵌套请求结果更新至目标对象

问题根因

你的代码中嵌套的图片下载Observable属于未被订阅的冷流,完全没有接入整个响应式链式结构:你在for循环内部创建了下载tile、拼接bitmap的流,但既没有将这个流返回给外层flatMap操作符,也没有将它的执行和当前tileLevels的发射逻辑做串联。RxJava中冷流只有在被下游订阅时才会执行,因此你写的doOnSuccess逻辑根本不会触发,tileLevel对象自然始终无法被更新。

修复方法

必须把预览图下载、Bitmap拼接的逻辑作为流的一部分串联到主链上,不能在操作符的lambda中创建孤立的流。核心调整点如下:

  • 遍历tileLevels找到第一个符合预览条件的对象后,将下载拼接逻辑作为当前flatMap的返回流,保证订阅触发时逻辑会按顺序执行
  • 等Bitmap拼接完成、tileLevel对象更新完毕后,再把完整的tileLevels列表发射给下游,供combineLatest组装ArtObject使用
  • 不要依赖doOnSuccess做核心业务状态更新,用map/flatMap等操作符把状态更新作为流执行的一部分,保证执行顺序可控
    修复后对应代码段(替换原getImageTileLevels后的flatMap逻辑即可):
.flatMap((Function<List<ImageTileLevel>, ObservableSource<List<ImageTileLevel>>>) imageTileLevels -> {
    // 查找第一个符合预览要求的tileLevel
    int previewPos = -1;
    for (int i = 0; i < imageTileLevels.size(); i++) {
        if (imageTileLevels.get(i).suitsForPreview()) {
            previewPos = i;
            break;
        }
    }
    // 无符合条件的预览层级直接返回原列表
    if (previewPos == -1) {
        return Observable.just(imageTileLevels);
    }

    ImageTileLevel targetLevel = imageTileLevels.get(previewPos);
    targetLevel.setPreview(true);
    // 下载、拼接逻辑接入主链,执行完成后再返回更新后的列表
    return Observable.fromIterable(targetLevel.getTiles())
            .concatMap(tile -> apiService.downloadFileWithDynamicUrlAsync(tile.getUrl())
                    .subscribeOn(Schedulers.io()))
            .toList()
            .map(responses -> {
                ArrayList<Bitmap> bitmaps = new ArrayList<>();
                for (Response<ResponseBody> resp : responses) {
                    if (resp.isSuccessful() && resp.body() != null) {
                        bitmaps.add(BitmapFactory.decodeStream(resp.body().byteStream()));
                    }
                }
                targetLevel.combineBitmaps(bitmaps);
                return imageTileLevels;
            })
            .toObservable();
})
优化提示
  • 你在getArtObjectInfo和getImageTileLevels处重复声明了subscribeOn(Schedulers.io()),最外层已经指定IO调度器的前提下可以移除,简化代码
  • Bitmap拼接属于CPU密集型操作,如果数据量较大,建议将拼接逻辑切换到Schedulers.computation()调度器,避免阻塞IO线程
  • 记得对ResponseBody做成功状态和空值判断,避免接口返回异常时触发空指针崩溃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 08:24:11