【安卓笔记】RxJava之flatMap的使用

发布于:2025-07-20 ⋅ 阅读:(16) ⋅ 点赞:(0)

0. 环境:

电脑:Windows10

Android Studio: 2024.3.2

编程语言: Java

Gradle version:8.11.1

Compile Sdk Version:35

Java 版本:Java11

1. 写该篇文章的由来

上篇文章中,最后的例子:

// 缩进过多的示范

// clicks 传入view, 也就是button这个view。此处是使用viewBinding框架
// Button btn = findViewById(R.id.button); 此处传入btn也是一样的
RxView.clicks(binding.buttonRequest)
        .throttleFirst(2000, TimeUnit.MILLISECONDS) //防抖动,2秒内只响应第1次
        .subscribe(new Consumer<Unit>() {//此处的Unit可以不用接收
            @Override
            public void accept(Unit unit) throws Throwable {
                // 网络请求,获取项目http。与getProjectHttp() 函数一样
                netApi.getProject()
                        .compose(rxud())
                        .subscribe(new Consumer<ProjectBean>() {
                            @Override
                            public void accept(ProjectBean projectBean) throws Throwable {
                                Log.i(TAG, "accept: " + projectBean);
                                // 此处可以通过获得的projectBean,继续请求Item
                                for (ProjectBean.DataDTO data : projectBean.getData()) {
                                    netApi.getProjectItem(1,data.getId())
                                            .compose(rxud())
                                            .subscribe(new Consumer<ItemBean>() {
                                                @Override
                                                public void accept(ItemBean itemBean) throws Throwable {
                                                    Log.i(TAG, "accept: " + itemBean);
                                                }
                                            });
                                }
                            }
                        });
            }
        });

如果最后for循环中,替换成调用netApi,则会造成缩进的代码太多阅读困难的问题。

实际上,现在只有两个网络请求。当数量继续增加时,缩进的代码会更多。非常不优雅 

2. 优化1.中的代码

先贴上最终代码:

// clicks 传入view, 也就是button这个view。此处是使用viewBinding框架
// Button btn = findViewById(R.id.button); 此处传入btn也是一样的
RxView.clicks(binding.buttonRequest)
        .throttleFirst(2000, TimeUnit.MICROSECONDS) //防抖动,2秒内只响应第1次
        .observeOn(Schedulers.io()) // 切换成子线程
        .flatMap(new Function<Unit, ObservableSource<ProjectBean>>() {
            @Override
            public ObservableSource<ProjectBean> apply(Unit unit) throws Throwable {
                // 获取项目数据
                return netApi.getProject();
            }
        })
        .flatMap(new Function<ProjectBean, ObservableSource<ProjectBean.DataDTO>>() {
            @Override
            public ObservableSource<ProjectBean.DataDTO> apply(ProjectBean projectBean) throws Throwable {
                // 迭代器,遍历projectBean中 List<Data> 的数据
                return Observable.fromIterable(projectBean.getData());
            }
        })
        .flatMap(new Function<ProjectBean.DataDTO, ObservableSource<ItemBean>>() {
            @Override
            public ObservableSource<ItemBean> apply(ProjectBean.DataDTO dataDTO) throws Throwable {
                // 获取项目item的数据
                return netApi.getProjectItem(1, dataDTO.getId());
            }
        })
        .observeOn(AndroidSchedulers.mainThread()) // 切换到主线程,方便操作UI
        .subscribe(new Consumer<ItemBean>() {
            @Override
            public void accept(ItemBean itemBean) throws Throwable {
                // 最后得到 item,操作UI
                Log.i(TAG, "accept: " + itemBean.toString());
            }
        })
;

其中代码对比:

第一个,获取项目信息的http的部分:

// 旧代码
.subscribe(new Consumer<Unit>() {//此处的Unit可以不用接收
    @Override
    public void accept(Unit unit) throws Throwable {
        // 网络请求,获取项目http。与getProjectHttp() 函数一样
        netApi.getProject()
                ·····
    }
});

// 等价于

// 优化后的代码
.flatMap(new Function<Unit, ObservableSource<ProjectBean>>() {
    @Override
    public ObservableSource<ProjectBean> apply(Unit unit) throws Throwable {
        // 获取项目数据
        return netApi.getProject();
    }
})

 第二个,for循环部分

// 旧代码
for (ProjectBean.DataDTO data : projectBean.getData()) {
    ····
}

// 等价于

// 优化后的代码
.flatMap(new Function<ProjectBean, ObservableSource<ProjectBean.DataDTO>>() {
    @Override
    public ObservableSource<ProjectBean.DataDTO> apply(ProjectBean projectBean) throws Throwable {
        // 迭代器,遍历projectBean中 List<Data> 的数据
        return Observable.fromIterable(projectBean.getData());
    }
})

第三个,获取item信息的http的部分:

// 旧代码
netApi.getProjectItem(1,data.getId())
        .compose(rxud())
        ···

// 等价于

//优化后的代码
.flatMap(new Function<ProjectBean.DataDTO, ObservableSource<ItemBean>>() {
    @Override
    public ObservableSource<ItemBean> apply(ProjectBean.DataDTO dataDTO) throws Throwable {
        // 获取项目item的数据
        return netApi.getProjectItem(1, dataDTO.getId());
    }
})

最后的.subscribe是一样的。

比较难理解的部分,在于for循环等价于迭代器,也就是第二步。

稍微解释一下,ObservableSource对象可以往下一张卡片发多次对象。

通过Observable.fromIterable(projectBean.getData()); 就可以遍历projectBean.getData()(即List<Data>)数组中的所有数据。

下一张卡片,会一条一条收到数据,并且一条一条按业务逻辑处理。

这样就可以提高代码可阅读性,解决缩进过多的问题

3. 写在最后

.flatMap 稍微难理解,但是也稍微高级。

请多查阅资料,务必弄懂该函数。

你与其他程序员的差距,就在此刻体现。

请加油学习。

关于RxJava,可以查看我其他文章:

【安卓笔记】RxJava的使用+修改功能+搭配retrofit+RxView防快速点击:【安卓笔记】RxJava的使用+修改功能+搭配retrofit+RxView防快速点击-CSDN博客

【安卓笔记】RxJava之flatMap的使用:【安卓笔记】RxJava之flatMap的使用-CSDN博客

【安卓笔记】RxJava的onNextDo的使用:【安卓笔记】RxJava的doOnNext的使用-CSDN博客

 【安卓笔记】RxJava的Hook机制,整体拦截器:https://blog.csdn.net/liosen/article/details/149467298


网站公告

今日签到

点亮在社区的每一天
去签到