RxJava基础使用

news2024/11/16 5:45:41

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 事件是path
    Observable.just(path)
            //2 拦截 将String->Bitmap 从网络中获取图片
            .map(new Function<String, Bitmap>() {
                @Override
                public Bitmap apply(String path) throws Exception {
                    //根据path获取Bitmap
                    Log.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>() {
                @Override
                public Bitmap apply(Bitmap bitmap) throws Exception {
                    Log.e(TAG,"3-给图片添加水印(Bitmap->Bitmap) currentThread = "+Thread.currentThread());
                    return bitmap;
                }
            })
            //4 终点 类型是上一个拦截者的返回类型 添加水印后的Bitmap
            .subscribe(new Observer<Bitmap>() {
                @Override
                public void onSubscribe(Disposable d) {
                    //代码执行从此处开始
                    Log.e(TAG,"1-subscribe:onSubscribe currentThread = "+Thread.currentThread());
                    progressDialog = new ProgressDialog(MainActivity.this);
                    progressDialog.show();
                }

                @Override
                public void onNext(Bitmap value) {
                    //5 获取成功 显示图片
                    Log.e(TAG,"4-获取成功,显示图片 currentThread = "+Thread.currentThread());
                    //显示图片
                    ((ImageView)findViewById(R.id.imageview)).setImageBitmap(value);
                }

                @Override
                public void onError(Throwable e) {
                    //执行失败
                    Log.e(TAG,"4-失败 currentThread = "+Thread.currentThread());
                    if(progressDialog != null){
                        progressDialog.dismiss();
                    }
                }

                @Override
                public 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>(){
        @Override
        public ObservableSource<UD> apply(Observable<UD> upstream) {
            return upstream
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .map(new Function<UD, UD>() {
                        @Override
                        public 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";
    //起点 类型是 path
    Observable.just(path)
            //拦截 将String->Bitmap
            .map(new Function<String, Bitmap>() {
                @Override
                public Bitmap apply(String path) throws Exception {
                    //根据path获取Bitmap
                    Log.e(TAG,"2-使用path请求Bitmap(String->Bitmap) currentThread = "+Thread.currentThread());
                    return new HttpURLUtill().getBitmap(path);
                }
            })
            .compose(rxud())
            //终点 类型是上一个拦截者的返回类型 Bitmap
            .subscribe(new Observer<Bitmap>() {
                @Override
                public void onSubscribe(Disposable d) {
                    Log.e(TAG,"1-subscribe:onSubscribe currentThread = "+Thread.currentThread());
                    progressDialog = new ProgressDialog(MainActivity.this);
                    progressDialog.show();
                }

                @Override
                public void onNext(Bitmap value) {
                    //获取成功 显示图片
                    Log.e(TAG,"4-获取成功,显示图片 currentThread = "+Thread.currentThread());
                    //显示图片
                    ((ImageView)findViewById(R.id.imageview)).setImageBitmap(value);
                }

                @Override
                public void onError(Throwable e) {
                    Log.e(TAG,"4-失败 currentThread = "+Thread.currentThread());
                    if(progressDialog != null){
                        progressDialog.dismiss();
                    }
                }

                @Override
                public 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";
    //起点 类型是 path
    Observable.just(path)
            //拦截 将String->Bitmap
            .map(new Function<String, Bitmap>() {
                @Override
                public Bitmap apply(String path) throws Exception {
                    //根据path获取Bitmap
                    Log.e(TAG,"2-使用path请求Bitmap(String->Bitmap) currentThread = "+Thread.currentThread());
                    return new HttpURLUtill().getBitmap(path);
                }
            })
            .compose(rxud())
            .doOnSubscribe(new Consumer<Disposable>() {
                @Override
                public 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>() {
                @Override
                public 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>() {
                @Override
                public 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>() { //观察者,获取结果
                @Override
                public 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>() {
                @Override
                public 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>() {
                                    @Override
                                    public 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>>() {
                @Override
                public ObservableSource<ProjectBean.DataBean> apply(ProjectBean projectBean) throws Exception {
                    return Observable.fromIterable(projectBean.getData());
                }
            })
           //根据项目分类id请求项目分类信息
            .flatMap(new Function<ProjectBean.DataBean, ObservableSource<ProjectItemBean>>() {
                @Override
                public 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>() {
                @Override
                public void accept(ProjectItemBean projectItemBean) throws Exception {
                    //获得项目分类信息
                    Log.e(TAG, projectItemBean.toString());
                }
            }, new Consumer<Throwable>() {
                @Override
                public 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>() {
                @Override
                public 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>>() {
                @Override
                public ObservableSource<ProjectBean.DataBean> apply(ProjectBean projectBean) throws Exception {
                    return Observable.fromIterable(projectBean.getData());
                }
            })
            //根据项目分类id请求项目分类信息
            .flatMap(new Function<ProjectBean.DataBean, ObservableSource<ProjectItemBean>>() {
                @Override
                public 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>() {
                @Override
                public void accept(ProjectItemBean projectItemBean) throws Exception {
                    //获得项目分类信息
                    Log.e(TAG, projectItemBean.toString());
                    ((TextView) findViewById(R.id.tv_project_item)).setText("我被更新了");
                }
            }, new Consumer<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    Log.e(TAG, "异常 一旦发生异常,整个链式调用就结束了");
                }
            });
}

防抖

使用RxView库。

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

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

相关文章

reshape函数及MATLAB应用

reshape 函数在 MATLAB 中是一个非常有用的函数&#xff0c;通过重新排列现有元素来重构数组。它允许你重新调整数组&#xff08;或矩阵&#xff09;的尺寸&#xff0c;而不改变其数据。这个函数特别适用于当你需要将一个矩阵或数组从一种结构转换为另一种结构时&#xff0c;只…

黑神话悟空是什么游戏 黑神话悟空配置要求 黑神话悟空好玩吗值得买吗 黑神话悟空苹果电脑可以玩吗

《黑神话&#xff1a;悟空》的类型定义是一款单机动作角色扮演游戏&#xff0c;但实际体验后会发现&#xff0c;游戏在很多设计上采用了「魂like」作品的常见元素。根据个人上手试玩&#xff0c;《黑神话&#xff1a;悟空》的推进节奏比较接近魂类游戏&#xff0c;Boss战也更像…

数据结构--双链表,循环链表,静态链表代码(王道书上代码手敲!!!)c++

目录 1.带头结点的双链表的初始化&#xff0c;判断链表是否为空&#xff0c;前插&#xff0c;后插&#xff0c;按位序插&#xff0c;删除后继节点&#xff0c;按位查找&#xff0c;按之查找&#xff0c;清空链表&#xff0c;销毁链表&#xff0c;遍历打印列表操作 2. 循环单链…

linux目录结构和重要文件

1. 目录介绍 操作Linux命令行&#xff0c;最基本的对象就是目录和文件&#xff0c;因为Linux中一切事物都是基于文件的&#xff0c;而目录就是文件的文件夹&#xff0c;所以接下来对一些基础且核心的文件目录管理命令进行说明。 1.1 目录结构 Linux系统目录结构是一个有层次…

达梦数据库的系统视图v$dict_cache

达梦数据库的系统视图v$dict_cache 达梦数据库系统视图V$DICT_CACHE主要用于监控和管理字典缓存的状态。字典缓存是数据库系统中用于存储元数据信息&#xff08;如表结构、索引信息等&#xff09;的缓存区域&#xff0c;它对于提高数据库查询性能至关重要。通过查询V$DICT_CAC…

Python 报错 SyntaxError: EOL while scanning string literal

Python 报错 SyntaxError: EOL while scanning string literal 在编程领域&#xff0c;尤其是使用Python这类解释型语言时&#xff0c;SyntaxError: EOL while scanning string literal 是一种常见的错误。这种错误通常发生在Python解释器尝试解析代码时&#xff0c;遇到了意外…

L-H、BytePlus 和 INOVAI在东京成功举办Web3 AI未来峰会

7月30日&#xff0c;L-H (Legendary Humanity)、字节跳动旗下BytePlus 和日本知名Web3孵化器 INOVAI 在东京联合举办Web3&AI未来峰会&#xff0c;水滴资本等行业重磅机构共同参与此次峰会&#xff0c;探讨AI与 Web3的融合性未来。 在此次峰会上&#xff0c;L-H (Legendary…

区块链软硬件协同,做产业数字化转型的“安全官” |《超话区块链》直播预告

今年的两会政府工作报告提出&#xff1a;“产业的数字化&#xff08;行业数字化转型&#xff09;是发展新质生产力的核心&#xff0c;是推动产业升级实现高质量发展的关键。”全面推进产业数字化&#xff0c;需要技术创新与产业应用深入协同&#xff1b;立足可持续发展的长远目…

动态面板数据实证模型及 Stata 具体操作步骤

目录 一、文献综述 二、理论原理 三、实证模型 四、稳健性检验 五、程序代码及解释 六、代码运行结果 一、文献综述 在经济学和社会科学的广袤领域中&#xff0c;动态面板数据模型逐渐成为研究者们探索复杂现象和关系的有力工具。众多杰出学者凭借这一模型在多个研究方向上…

30.x86游戏实战-遍历背包数组

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

弧形导轨的多样化驱动方式!

弧形导轨由导轨、导向滑块、传动机构等部分组成&#xff0c;是一种可以实现直线、圆弧、任意曲线运动的导向装置&#xff0c;广泛应用在机械设备中。弧形导轨的驱动方式具有多样性和灵活性&#xff0c;可以根据不同的应用场景和需求进行选择。 1、滚轮驱动&#xff1a;在弧形导…

全球汽车凸轮轴市场规模预测:未来六年CAGR为2.3%

随着汽车行业的持续发展和消费者对发动机性能的需求增加&#xff0c;汽车凸轮轴作为发动机核心部件之一&#xff0c;正逐渐受到市场的广泛关注。本文旨在通过深度分析汽车凸轮轴行业的各个维度&#xff0c;揭示行业发展趋势和潜在机会。 【市场趋势的演变】 1. 市场规模与增长…

VisualStudio 类设计器 组件的使用

总目录 前言 当我们需要快速熟悉一个新接手的软件系统框架及业务逻辑代码时&#xff0c;如果埋头一个个去捋顺&#xff0c;估计等你捋顺了&#xff0c;项目也结束了&#xff1b;应对这种情况最好方法就是先通过UML图去了解代码的宏观架构&#xff0c;然后有针对性的突破。VS中…

搭建Go语言gRPC微服务开发环境详细教程

文档&#xff1a;https://grpc.io/docs/languages/go/quickstart/ 下载protobuffer&#xff1a;https://github.com/protocolbuffers/protobuf/releases/tag/v27.2 解压到C:/dev目录&#xff1a; 将目录添加到环境变量&#xff1a; 打开终端进行测试&#xff1a; proto…

vite打包文件配置到IIS出现页面、图片加载不出来的问题

问题描述&#xff1a; 用vitevue3开发的项目&#xff0c;打包后放在服务器上&#xff0c;然后配置了IIS&#xff0c;用链接访问后出现白页面。 解决方案&#xff1a; 修改vite.config.js文件中的base路径&#xff1a;/改为./ 解决方案&#xff1a; 1.查看页面报错原因&…

雅致表达:看体育比赛 ,少不了的语文知识。

文章目录 引言捷报囊括当务之急问鼎凯旋折桂捞金曾几何时差强人意居功至伟一发不可收拾首当其冲不孚众望望其项背炙手可热美轮美奂摄氏度引言 随着巴黎奥运会各项赛事的展开,看到激动人心比赛画面的你,看到喜欢的选手圆梦的你,总会有冲动把喜悦分享出去,适当的用词为表达加…

MySQL笔记5——视图、存储过程和触发器

视图 创建视图 视图是从一个或几个基本表&#xff08;或视图&#xff09;导出的表。它与基本表不同&#xff0c;是一个虚表。 CREATE VIEW view_name as select…… 说明&#xff1a; view_name自己定义的视图名as后面是这个视图所用到的查询结果 视图的操作 视图的查询…

nodejs项目

一、基于域名配置server 1. 一个配置文件一般只有一个 http 模块 2. 一个 http 模块可以有多个 server 模块 3. 一个 server 模块就是一套 web 项目 4. 一个 server 模块中可以有多个 location 5. location 就是项目中的 url 路由 # 第一步 mkdir /zhangmin # 第…

GMII, SGMII 以太网接口

前言&#xff1a; &#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留…

(最全最小白易懂版)Yolov8新手教程-配置环境、数据集处理、目标检测、结果分析处理(图像指标、可视化结果)、报错分析等全过程学习记录

目录 一、安装环境&#xff08;配置yolo、demo测试&#xff09; 二、数据集准备&#xff08;格式学习&#xff09; 三、训练数据集 1.划分数据集 2.训练数据集 2.1常规训练 2.2微调 3.各种报错记录 3.1AttributeError 3.2TypeError 3.3Error while loading conda en…