RxJava基础使用

Rx思想

事件从起点流向终点。

过程中可以对事件进行拦截,拦截时可以对事件进行处理,处理后将处理后的事件继续流向终点。

终点接收上一次处理后的事件。


获取网络图片并显示

基础实现

使用Observable.just(path) 创建图片路径的Observable。

使用map添加拦截,将path转换为Bitmap。

使用map添加拦截,给Bitmap添加水印。

。。。。。随意添加拦截

使用subscribe订阅事件,将Bitmap显示到View中。

private void rxjavaGetBitmap() {Log.e(TAG,"rxjavaGetBitmap currentThread = "+Thread.currentThread());//图片路径String path = "https://pic2.zhimg.com/v2-0dda71bc9ced142bf7bb2d6adbebe4f0_r.jpg";//1 起点 类型是 path  创建Observable 事件是pathObservable.just(path)//2 拦截 将String->Bitmap 从网络中获取图片.map(new Function<String, Bitmap>() {@Overridepublic Bitmap apply(String path) throws Exception {//根据path获取BitmapLog.e(TAG,"2-使用path请求Bitmap(String->Bitmap) currentThread = "+Thread.currentThread());return new HttpURLUtill().getBitmap(path);}})// 上面代码子线程中执行.subscribeOn(Schedulers.io())// 下面代码在主线程执行.observeOn(AndroidSchedulers.mainThread())// 3 拦截 Bitmap->Bitmap 给图片添加水印.map(new Function<Bitmap, Bitmap>() {@Overridepublic Bitmap apply(Bitmap bitmap) throws Exception {Log.e(TAG,"3-给图片添加水印(Bitmap->Bitmap) currentThread = "+Thread.currentThread());return bitmap;}})//4 终点 类型是上一个拦截者的返回类型 添加水印后的Bitmap.subscribe(new Observer<Bitmap>() {@Overridepublic void onSubscribe(Disposable d) {//代码执行从此处开始Log.e(TAG,"1-subscribe:onSubscribe currentThread = "+Thread.currentThread());progressDialog = new ProgressDialog(MainActivity.this);progressDialog.show();}@Overridepublic void onNext(Bitmap value) {//5 获取成功 显示图片Log.e(TAG,"4-获取成功,显示图片 currentThread = "+Thread.currentThread());//显示图片((ImageView)findViewById(R.id.imageview)).setImageBitmap(value);}@Overridepublic void onError(Throwable e) {//执行失败Log.e(TAG,"4-失败 currentThread = "+Thread.currentThread());if(progressDialog != null){progressDialog.dismiss();}}@Overridepublic void onComplete() {//6 执行结束Log.e(TAG,"5-完成 currentThread = "+Thread.currentThread());if(progressDialog != null){progressDialog.dismiss();}}});
}

中断

对于异步执行的耗时操作,需要使用Disposable实现中断。

在流程开始的时候,保存Disposable对象(在Observer中的onSubscribe时保存Disposable对象)

在Activity onDestory()时如果该流程没有执行完成,需要中断该流程,否则在执行流程结束更新UI的时候,会出现空指针异常。


Rx思想流程

代码执行流程


抽离公共代码 comose

ObservableTransformer+compose

抽离线程切换和添加水印部分功能为ObservableTransformer,使用compose操作符,使用ObservableTransformer。

/*** 将部分流程抽离出来共用,使用ObservableTransformer* @return* @param <UD>                    */
private <UD> ObservableTransformer<UD, UD>  rxud(){return new ObservableTransformer<UD, UD>(){@Overridepublic ObservableSource<UD> apply(Observable<UD> upstream) {return upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).map(new Function<UD, UD>() {@Overridepublic UD apply(UD ud) throws Exception {Log.e(TAG,"3-给图片添加水印(Bitmap->Bitmap) currentThread = "+Thread.currentThread());return ud;}});}};
}/*** 抽离部分内容为方法*/
private void rxjavaGetBitmap2() {Log.e(TAG,"rxjavaGetBitmap currentThread = "+Thread.currentThread());String path = "https://pic2.zhimg.com/v2-0dda71bc9ced142bf7bb2d6adbebe4f0_r.jpg";//起点 类型是 pathObservable.just(path)//拦截 将String->Bitmap.map(new Function<String, Bitmap>() {@Overridepublic Bitmap apply(String path) throws Exception {//根据path获取BitmapLog.e(TAG,"2-使用path请求Bitmap(String->Bitmap) currentThread = "+Thread.currentThread());return new HttpURLUtill().getBitmap(path);}}).compose(rxud())//终点 类型是上一个拦截者的返回类型 Bitmap.subscribe(new Observer<Bitmap>() {@Overridepublic void onSubscribe(Disposable d) {Log.e(TAG,"1-subscribe:onSubscribe currentThread = "+Thread.currentThread());progressDialog = new ProgressDialog(MainActivity.this);progressDialog.show();}@Overridepublic void onNext(Bitmap value) {//获取成功 显示图片Log.e(TAG,"4-获取成功,显示图片 currentThread = "+Thread.currentThread());//显示图片((ImageView)findViewById(R.id.imageview)).setImageBitmap(value);}@Overridepublic void onError(Throwable e) {Log.e(TAG,"4-失败 currentThread = "+Thread.currentThread());if(progressDialog != null){progressDialog.dismiss();}}@Overridepublic void onComplete() {//第四步 结束执行Log.e(TAG,"5-完成 currentThread = "+Thread.currentThread());if(progressDialog != null){progressDialog.dismiss();}}});
}

简化观察者 Consumer

Observer-> Consumer

/*** 简化订阅者*/
private void rxjavaGetBitmap3() {Log.e(TAG,"rxjavaGetBitmap currentThread = "+Thread.currentThread());String path = "https://pic2.zhimg.com/v2-0dda71bc9ced142bf7bb2d6adbebe4f0_r.jpg";//起点 类型是 pathObservable.just(path)//拦截 将String->Bitmap.map(new Function<String, Bitmap>() {@Overridepublic Bitmap apply(String path) throws Exception {//根据path获取BitmapLog.e(TAG,"2-使用path请求Bitmap(String->Bitmap) currentThread = "+Thread.currentThread());return new HttpURLUtill().getBitmap(path);}}).compose(rxud()).doOnSubscribe(new Consumer<Disposable>() {@Overridepublic void accept(Disposable disposable) throws Exception {Log.e(TAG,"1-subscribe:onSubscribe currentThread = "+Thread.currentThread());progressDialog = new ProgressDialog(MainActivity.this);progressDialog.show();}})//终点 类型是上一个拦截者的返回类型 Bitmap.subscribe(new Consumer<Bitmap>() {@Overridepublic void accept(Bitmap bitmap) throws Exception {//第三步 获取成功 显示图片Log.e(TAG,"4-获取成功,显示图片 currentThread = "+Thread.currentThread());//显示图片((ImageView)findViewById(R.id.imageview)).setImageBitmap(bitmap);if(progressDialog != null){progressDialog.dismiss();}}}, new Consumer<Throwable>() {@Overridepublic void accept(Throwable throwable) throws Exception {Log.e(TAG,"4-失败 currentThread = "+Thread.currentThread());if(progressDialog != null){progressDialog.dismiss();}}});
}

RxJava+Retrofit

单个接口

请求执行类型使用RxJava的Observable,网络请求后返回的直接是RxJava的被观察者Observable。

相当于通过Observable.just(path)获取到Observable。

然后可以对Observable执行拦截、订阅。

Retrofit Api接口类:使用玩Android 开放API 玩Android 开放API-玩Android - wanandroid.com

public interface NetWorkApi {//获取项目分类@GET("project/tree/json")Observable<ProjectBean> getProject();//获取项目分类下的信息@GET("project/list/{pageIndex}/json")Observable<ProjectItemBean> getProjectItem(@Path("pageIndex") int  pageIndex, @Query("cid") String cid);
}

获取到项目分类信息

//获取Retrofit
public Retrofit getRetrofit(){return new Retrofit.Builder().baseUrl("https://www.wanandroid.com/")//Gson解析.addConverterFactory(GsonConverterFactory.create())//Rxjava CallAdapter.addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();
}public void getProjectInfo(View view) {//获取项目分类getRetrofit().create(NetWorkApi.class)  //获取Retrofit api实现类.getProject() //获取Observable<ProjectBean>.subscribeOn(Schedulers.io()) //上面代码在子线程中执行.observeOn(AndroidSchedulers.mainThread()) //下面代码在主线程中执行.subscribe(new Consumer<ProjectBean>() { //观察者,获取结果@Overridepublic void accept(ProjectBean projectBean) throws Exception {Log.e(TAG, projectBean.toString());}});
}

多个接口网络嵌套 flatMap

顺序请求两个接口的数据后更新UI。

网络嵌套的方法。

//网络嵌套写法
@SuppressLint("CheckResult")
private void networkNesting(){//获取项目分类getRetrofit().create(NetWorkApi.class).getProject().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<ProjectBean>() {@Overridepublic void accept(ProjectBean projectBean) throws Exception {Log.e(TAG, projectBean.toString());for (ProjectBean.DataBean datum : projectBean.getData()) {//根据分类id获取项目列表数据getRetrofit().create(NetWorkApi.class).getProjectItem(1, datum.getId()).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<ProjectItemBean>() {@Overridepublic void accept(ProjectItemBean projectItemBean) throws Exception {Log.e(TAG, projectItemBean.toString());}});}}});
}

使用flatMap解决上述网络嵌套问题,将一个事件变为多个事件。

ps:任何一个位置发生异常,整个流程结束执行。

@SuppressLint("CheckResult")
private void noNesting(){//获取项目分类getRetrofit().create(NetWorkApi.class).getProject().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())//循环项目分类 1个Observable转多个Observable.flatMap(new Function<ProjectBean, ObservableSource<ProjectBean.DataBean>>() {@Overridepublic ObservableSource<ProjectBean.DataBean> apply(ProjectBean projectBean) throws Exception {return Observable.fromIterable(projectBean.getData());}})//根据项目分类id请求项目分类信息.flatMap(new Function<ProjectBean.DataBean, ObservableSource<ProjectItemBean>>() {@Overridepublic ObservableSource<ProjectItemBean> apply(ProjectBean.DataBean dataBean) throws Exception {Log.e(TAG, dataBean.toString());return getRetrofit().create(NetWorkApi.class).getProjectItem(1, dataBean.getId());}}).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<ProjectItemBean>() {@Overridepublic void accept(ProjectItemBean projectItemBean) throws Exception {//获得项目分类信息Log.e(TAG, projectItemBean.toString());}}, new Consumer<Throwable>() {@Overridepublic void accept(Throwable throwable) throws Exception {Log.e(TAG, "异常 一旦发生异常,整个链式调用就结束了");}});
}

多个接口过程中更新UI doOnNext

顺序请求两个接口,并在每个接口请求结束后更新相应的UI。

使用doOnNext操作符实现。

private void updateProjectAndProjectItemInfo() {getRetrofit().create(NetWorkApi.class).getProject().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())//获取到项目分类信息后,执行UI操作.doOnNext(new Consumer<ProjectBean>() {@Overridepublic void accept(ProjectBean dataBean) throws Exception {((TextView) findViewById(R.id.tv_project)).setText("我被更新了");}}).observeOn(Schedulers.io())//循环项目分类 1个Observable转多个Observable.flatMap(new Function<ProjectBean, ObservableSource<ProjectBean.DataBean>>() {@Overridepublic ObservableSource<ProjectBean.DataBean> apply(ProjectBean projectBean) throws Exception {return Observable.fromIterable(projectBean.getData());}})//根据项目分类id请求项目分类信息.flatMap(new Function<ProjectBean.DataBean, ObservableSource<ProjectItemBean>>() {@Overridepublic ObservableSource<ProjectItemBean> apply(ProjectBean.DataBean dataBean) throws Exception {Log.e(TAG, dataBean.toString());return getRetrofit().create(NetWorkApi.class).getProjectItem(1, dataBean.getId());}}).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<ProjectItemBean>() {@Overridepublic void accept(ProjectItemBean projectItemBean) throws Exception {//获得项目分类信息Log.e(TAG, projectItemBean.toString());((TextView) findViewById(R.id.tv_project_item)).setText("我被更新了");}}, new Consumer<Throwable>() {@Overridepublic void accept(Throwable throwable) throws Exception {Log.e(TAG, "异常 一旦发生异常,整个链式调用就结束了");}});
}

防抖

使用RxView库。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/51904.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity | Shader基础知识(第二十集:应用-简易流光、LOD)

目录 一、前言 二、LOD 1.什么是LOD 2.代码如何调节LOD 三、流光 1.资源准备 2.uv移动 3.获取图片中的uv 4.改变uv去取流光的颜色&#xff08;时间的应用&#xff09; 5.图片叠加 6.透明图片的叠加 四、纯净代码 五、作者的碎碎念 一、前言 有小伙伴问&#xf…

Studying-代码随想录训练营day45| 115.不同的子序列、583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结篇

第45天&#xff0c;子序列part03&#xff0c;编辑距离&#x1f4aa;(ง •_•)ง&#xff0c;编程语言&#xff1a;C 目录 115.不同的子序列 583. 两个字符串的删除操作 72. 编辑距离 编辑距离总结篇 115.不同的子序列 文档讲解&#xff1a;代码随想录不同的子序列 视频讲…

分布式搜索引擎ES--Elasticsearch集群

1.Elasticsearch集群的概念 分片机制&#xff1a;每个索引都可以被分片 索引my_doc只有一个主分片&#xff1b;索引shop有三个主分片&#xff1b;索引shop2有5个主分片;(参考前面案例) 每个主分片都包含索引的数据&#xff0c;由于目前是单机&#xff0c;所以副分片是没有的&a…

安全开发第一篇

文章目录 参与RASP、IAST等安全防护工具的开发技术背景开发流程技术挑战工具和资源示例结论 以phpstudydvwa为列 实现 SQL 注入检测脚本 参与RASP、IAST等安全防护工具的开发 参与 RASP&#xff08;Runtime Application Self-Protection&#xff09;和 IAST&#xff08;Intera…

为开源奉献一份自己的力量:Cesium没有热力图组件,我们自己封装!

大家好&#xff0c;我是日拱一卒的攻城师不浪&#xff0c;专注可视化、数字孪生、前端提效、nodejs、AI学习、GIS等学习沉淀&#xff0c;这是2024年输出的第27/100篇文章。 交流合作&#xff1a;brown_7778 前言 热力图&#xff0c;在很多可视化场景开发中会被经常提到&#x…

electron 主进程和渲染进程

最近在整理electron 相关的项目问题&#xff0c;对自己来说也是温故知新&#xff0c;也希望能对小伙伴们有所帮助&#xff0c;大家共同努力共同进步。加油&#xff01;&#xff01;&#xff01;&#xff01; 虽然最近一年前端大环境不好&#xff0c;但是大家还是要加油鸭&#…

网安零基础入门神书,全面介绍Web渗透核心攻击与防御方式!

Web安全是指Web服务程序的漏洞&#xff0c;通常涵盖Web漏洞、操作系统洞、数据库漏洞、中间件漏洞等。 “渗透测试”作为主动防御的一种关键手段&#xff0c;对评估网络系统安全防护及措施至关重要&#xff0c;因为只有发现问题才能及时终止并预防潜在的安全风险。 根据网络安…

【Qt开发】No matching signal for on_toolButton_clicked() 解决方案

【Qt开发】No matching signal for on_toolButton_clicked() 解决方案 文章目录 No matching signal for xxx 解决方案附录&#xff1a;C语言到C的入门知识点&#xff08;主要适用于C语言精通到Qt的C开发入门&#xff09;C语言与C的不同C中写C语言代码C语言到C的知识点Qt开发中…

Linux安装青龙面板并将本地服务映射至公网实现远程访问

文章目录 前言一、前期准备本教程环境为&#xff1a;Centos7&#xff0c;可以跑Docker的系统都可以使用。本教程使用Docker部署青龙&#xff0c;如何安装Docker详见&#xff1a; 二、安装青龙面板三、映射本地部署的青龙面板至公网四、使用固定公网地址访问本地部署的青龙面板 …

全局异常 @ControllerAdvice 该怎么写

本文首发于稀土掘金&#xff1a;全局异常 ControllerAdvice 该怎么写&#xff0c;该账号即为本人账号&#xff0c;非搬运。 问题由来 很多小伙伴刚进公司做项目的时候&#xff0c;会看到项目里面有一个ControllerAdvice标记的类&#xff0c;整个类的编码结构大概是这样子&…

程序员极力推荐的几款插件

前言 h之前分享程序员喜欢的神器之后&#xff0c;还是相当多的伙伴喜欢&#xff0c;那一期的工具不仅是协助你工作还是工作外摸鱼划水&#xff0c;体验感是相当不错的。 这一期我还是打算把我非常喜欢用的几款插件分享给大家&#xff0c;这几款差劲不仅帮助我节省很多时间&am…

2024年软件系统与信息处理国际会议(ICSSIP 2024)即将召开!

2024年软件系统与信息处理国际会议&#xff08;ICSSIP 2024&#xff09;将于2024年10月25-27日在中国昆明举行。引领技术前沿&#xff0c;共谋创新未来。ICSSIP 2024将汇聚来自世界各地的专家学者&#xff0c;他们将在会上分享最新的研究成果、技术突破及实践经验。会议议题涵盖…

WAAP替代传统WAF已成趋势

数字化时代&#xff0c;Web应用和API已成为企业运营的核心。然而&#xff0c;随着网络攻击手段的不断进化&#xff0c;自动化攻击愈发频繁&#xff0c;传统的Web应用防火墙&#xff08;WAF&#xff09;已难以满足现代企业的安全需求。WAAP&#xff08;Web Application and API …

我出一道面试题,看看你能拿 3k 还是 30k!

大家好&#xff0c;我是程序员鱼皮。欢迎屏幕前的各位来到今天的模拟面试现场&#xff0c;接下来我会出一道经典的后端面试题&#xff0c;你只需要进行 4 个简单的选择&#xff0c;就能判断出来你的水平是新手&#xff08;3k&#xff09;、初级&#xff08;10k&#xff09;、中…

大镜山阿里巴巴国际站数据采集软件使用方法|阿里国际站商家信息采集软件使用方法|阿里国际站信息采集软件使用方法

大镜山阿里巴巴国际站数据采集软件一款采集阿里巴巴国际站alibaba.com商家数据的软件&#xff0c;采集的数据包括店铺名称、店铺年份、评分、邮件地址、手机号码、网址及社交连接等。 下载大镜山阿里巴巴国际站数据采集软件 大镜山阿里巴巴国际站数据采集软件下载地址 大镜山…

ubuntu20.04.6 安装Skywalking 10.0.1

1.前置准备 1.1. **jdk17&#xff08;Skywalking10 jdk22不兼容&#xff0c;用17版本即可&#xff09;**安装&#xff1a; https://blog.csdn.net/CsethCRM/article/details/140768670 1.2. elasticsearch安装&#xff1a; https://blog.csdn.net/CsethCRM/article/details…

Java-21推崇的虚拟线程到底有好快?一起来看这个实验

我们一起来看下面这个场景&#xff1a;十万个待执行任务&#xff0c;每个任务休眠两秒 1. 采用java-21的虚拟线程池来实现 public static void main(String[] args) throws InterruptedException{ExecutorService VIRTUAL_THREAD_POOL Executors.newThreadPerTaskExecutor(Th…

爬虫程序在采集亚马逊站点数据时如何绕过验证码限制?

引言 在电商数据分析中&#xff0c;爬虫技术的应用日益广泛。通过爬虫技术&#xff0c;我们可以高效地获取大量的电商平台数据&#xff0c;这些数据对于市场分析、竞争情报、价格监控等有着极其重要的意义。亚马逊作为全球最大的电商平台之一&#xff0c;是数据采集的重要目标…

pdf文件损坏打不开怎么修复?文档损坏原因和修复办法分享!

pdf是一种优点很多的软件&#xff0c;它在文件传输过程中格式不会乱掉&#xff0c;而且还可以加密&#xff0c;特别的方便。pdf这种文件格式&#xff0c;不仅能呈现文档&#xff0c;还可以呈现图像&#xff0c;工作中经常会用到。 不过&#xff0c;因为种种原因&#xff0c;有…

【iOS】——Block底层实现和捕获机制

Block的实质 Block的定义是带有自动变量的匿名函数&#xff0c;下面从源码的角度探究下Block究竟是什么 下面是一个Block的简单实现&#xff1a; int main(int argc, const char * argv[]) {autoreleasepool {// insert code here...void (^blk)(void) ^{printf("Bloc…