【安卓笔记】RxJava之flatMap的使用
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可以不用接收@Overridepublic void accept(Unit unit) throws Throwable {// 网络请求,获取项目http。与getProjectHttp() 函数一样netApi.getProject().compose(rxud()).subscribe(new Consumer<ProjectBean>() {@Overridepublic void accept(ProjectBean projectBean) throws Throwable {Log.i(TAG, "accept: " + projectBean);// 此处可以通过获得的projectBean,继续请求Itemfor (ProjectBean.DataDTO data : projectBean.getData()) {netApi.getProjectItem(1,data.getId()).compose(rxud()).subscribe(new Consumer<ItemBean>() {@Overridepublic 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>>() {@Overridepublic ObservableSource<ProjectBean> apply(Unit unit) throws Throwable {// 获取项目数据return netApi.getProject();}}).flatMap(new Function<ProjectBean, ObservableSource<ProjectBean.DataDTO>>() {@Overridepublic ObservableSource<ProjectBean.DataDTO> apply(ProjectBean projectBean) throws Throwable {// 迭代器,遍历projectBean中 List<Data> 的数据return Observable.fromIterable(projectBean.getData());}}).flatMap(new Function<ProjectBean.DataDTO, ObservableSource<ItemBean>>() {@Overridepublic ObservableSource<ItemBean> apply(ProjectBean.DataDTO dataDTO) throws Throwable {// 获取项目item的数据return netApi.getProjectItem(1, dataDTO.getId());}}).observeOn(AndroidSchedulers.mainThread()) // 切换到主线程,方便操作UI.subscribe(new Consumer<ItemBean>() {@Overridepublic void accept(ItemBean itemBean) throws Throwable {// 最后得到 item,操作UILog.i(TAG, "accept: " + itemBean.toString());}})
;
其中代码对比:
第一个,获取项目信息的http的部分:
// 旧代码
.subscribe(new Consumer<Unit>() {//此处的Unit可以不用接收@Overridepublic void accept(Unit unit) throws Throwable {// 网络请求,获取项目http。与getProjectHttp() 函数一样netApi.getProject()·····}
});// 等价于// 优化后的代码
.flatMap(new Function<Unit, ObservableSource<ProjectBean>>() {@Overridepublic ObservableSource<ProjectBean> apply(Unit unit) throws Throwable {// 获取项目数据return netApi.getProject();}
})
第二个,for循环部分
// 旧代码
for (ProjectBean.DataDTO data : projectBean.getData()) {····
}// 等价于// 优化后的代码
.flatMap(new Function<ProjectBean, ObservableSource<ProjectBean.DataDTO>>() {@Overridepublic 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>>() {@Overridepublic 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防快速点击:https://blog.csdn.net/liosen/article/details/149340103
【安卓笔记】RxJava之flatMap的使用:https://blog.csdn.net/liosen/article/details/149343166
【安卓笔记】RxJava的onNextDo的使用:https://blog.csdn.net/liosen/article/details/149343321