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

如何在所有并行HTTP请求完成后调用方法?(RxJava实现需求)

不用Lambda的RxJava实现方案

没问题,我给你整理一套不用lambda的RxJava实现方案,完美匹配你的需求——先批量获取分类,再逐个拉取对应频道,等所有数据都拿到后再执行最终方法:

第一步:改造Retrofit接口

首先把原来的Call返回类型改成Observable,这样才能和RxJava无缝配合,同时补充获取频道的接口:

public interface VideoAPI {
    @GET("/api/{categoryId}")
    Observable<Category> getCategory(@Path("categoryId") String categoryId);

    // 假设你的频道接口是这样的,根据实际情况调整
    @GET("/api/categories/{categoryId}/channels")
    Observable<List<Channel>> getChannels(@Path("categoryId") String categoryId);
}

第二步:核心实现代码

接下来写具体的业务逻辑,全程用匿名内部类,完全不用lambda:

private void loadAllCategoriesAndChannels() {
    // 1. 把tabs列表转成Observable,逐个处理每个Tab
    Observable.fromIterable(tabs)
            // 发起分类请求,将Tab转换为Category的Observable
            .flatMap(new Function<Tab, Observable<Category>>() {
                @Override
                public Observable<Category> apply(Tab tab) throws Exception {
                    return videoAPI.getCategory(tab.getId())
                            // 处理单个分类请求失败的情况,避免整个流中断
                            .onErrorReturn(new Function<Throwable, Category>() {
                                @Override
                                public Category apply(Throwable throwable) throws Exception {
                                    Log.i(TAG, "获取分类失败: " + throwable.getLocalizedMessage());
                                    return null; // 也可以返回空Category对象,根据需求调整
                                }
                            });
                }
            })
            // 过滤掉获取失败的分类(如果返回null的话)
            .filter(new Predicate<Category>() {
                @Override
                public boolean test(Category category) throws Exception {
                    return category != null;
                }
            })
            // 对每个分类,发起频道请求,绑定分类和频道数据
            .flatMap(new Function<Category, Observable<CategoryWithChannels>>() {
                @Override
                public Observable<CategoryWithChannels> apply(final Category category) throws Exception {
                    return videoAPI.getChannels(category.getId())
                            // 将频道列表和分类绑定成一个对象
                            .map(new Function<List<Channel>, CategoryWithChannels>() {
                                @Override
                                public CategoryWithChannels apply(List<Channel> channels) throws Exception {
                                    return new CategoryWithChannels(category, channels);
                                }
                            })
                            // 处理单个频道请求失败的情况
                            .onErrorReturn(new Function<Throwable, CategoryWithChannels>() {
                                @Override
                                public CategoryWithChannels apply(Throwable throwable) throws Exception {
                                    Log.i(TAG, "获取频道失败: " + throwable.getLocalizedMessage());
                                    // 即使频道获取失败,也保留分类信息
                                    return new CategoryWithChannels(category, new ArrayList<Channel>());
                                }
                            });
                }
            })
            // 等待所有请求完成,收集所有结果为一个List
            .toList()
            // 指定网络请求在IO线程执行
            .subscribeOn(Schedulers.io())
            // 指定结果处理在主线程(Android环境下必须)
            .observeOn(AndroidSchedulers.mainThread())
            // 订阅结果
            .subscribe(new Observer<List<CategoryWithChannels>>() {
                @Override
                public void onSubscribe(Disposable d) {
                    // 可选:保存Disposable,用于在页面销毁时取消请求
                    // disposable = d;
                }

                @Override
                public void onNext(List<CategoryWithChannels> allData) {
                    // 这里已经拿到所有分类和对应的频道数据了
                    categories.clear();
                    for (CategoryWithChannels item : allData) {
                        categories.add(item.getCategory());
                        // 可以在这里保存频道数据,比如:
                        // channelMap.put(item.getCategory().getId(), item.getChannels());
                    }
                    // 调用你需要的最终方法
                    onAllDataLoadedSuccessfully();
                }

                @Override
                public void onError(Throwable e) {
                    Log.i(TAG, "整体加载出错: " + e.getLocalizedMessage());
                    // 可选:处理整体出错的情况,比如提示用户
                }

                @Override
                public void onComplete() {
                    // onNext执行后会触发这个方法,一般不需要额外逻辑
                }
            });
}

// 辅助类:用来绑定分类和对应的频道数据,方便后续统一处理
private static class CategoryWithChannels {
    private final Category category;
    private final List<Channel> channels;

    public CategoryWithChannels(Category category, List<Channel> channels) {
        this.category = category;
        this.channels = channels;
    }

    public Category getCategory() {
        return category;
    }

    public List<Channel> getChannels() {
        return channels;
    }
}

// 你需要的最终回调方法:所有数据加载完成后调用
private void onAllDataLoadedSuccessfully() {
    // 这里写所有数据准备好后的业务逻辑
}

第三步:配置依赖和Retrofit

确保你的项目中添加了必要的依赖:

// RxJava核心库
implementation 'io.reactivex.rxjava2:rxjava:2.2.21'
// RxAndroid:适配Android线程
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
// Retrofit的RxJava适配器
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
// 别忘了Retrofit和Gson转换器(如果用的话)
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

创建Retrofit实例时,要添加RxJava2CallAdapterFactory:

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("你的服务器基础URL")
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .build();
VideoAPI videoAPI = retrofit.create(VideoAPI.class);

关键逻辑说明

  • Observable.fromIterable(tabs):把tabs集合转换成Observable,逐个发射每个Tab对象;
  • flatMap:用来将一个Observable转换成另一个Observable,这里用来发起网络请求,把Tab转换成Category,再把Category转换成带频道的对象;
  • onErrorReturn:处理单个请求失败的情况,保证整个数据流不会因为某一个请求失败而中断;
  • toList():等待所有Observable都发射完数据,然后把结果收集成一个List,这样就能确保所有数据都加载完成后才执行后续逻辑;
  • subscribeOn和observeOn:分别指定网络请求在IO线程,结果处理在主线程,符合Android的线程规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:03:41