RxJava和Retrofit的介绍

2024-06-09 01:58
文章标签 java 介绍 retrofit rx

本文主要是介绍RxJava和Retrofit的介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、ReactiveX简单介绍

Rx是一个使用可观察数据流进行异步编程的编程接口,ReactiveX结合了观察者模式、迭代器模式和函数式编程的精华。Rx提供了一系列的操作符,你可以使用它们来过滤(filter)、选择(select)、变换(transform)、结合(combine)和组合(compose)多个Observable,这些操作符让执行和复合变得非常高效。

在ReactiveX中,一个观察者(Observer)订阅一个可观察对象(Observable)。观察者对Observable发射的数据或数据序列作出响应。这种模式可以极大地简化并发操作,因为它创建了一个处于待命状态的观察者哨兵,在未来某个时刻响应Observable的通知,不需要阻塞等待Observable发射数据。

上图取自ReactiveX官方文档,上面一排图标代表被观察对象产生的事件,横向的箭头代表时间线,有6个事件依次发射,经过中间的转换和处理得到了下面的图标,即处理结果,有些事件发射、处理和接收都成功,而有些事件因为各种原因导致失败,这些情况都会在相应的回调方法中呈现。

Subscribe方法用于将观察者连接到Observable,你的观察者需要实现以下方法的一个子集:

  • onNext(T item)

    Observable调用这个方法发射数据,方法的参数就是Observable发射的数据,这个方法可能会被调用多次,取决于你的实现。

  • onError(Exception ex)

    当Observable遇到错误或者无法返回期望的数据时会调用这个方法,这个调用会终止Observable,后续不会再调用onNext和onCompleted,onError方法的参数是抛出的异常。

  • onComplete

    正常终止,如果没有遇到错误,Observable在最后一次调用onNext之后调用此方法。

根据Observable协议的定义,onNext可能会被调用零次或者很多次,最后会有一次onCompleted或onError调用(不会同时),传递数据给onNext通常被称作发射,onCompleted和onError被称作通知。

二、RxJava与RxAndroid的配合使用

RxJava是 ReactiveX 在JVM上的一个实现,ReactiveX使用Observable序列组合异步和基于事件的程序。RxJava提供了5种调度器,分别是:

  • .io()

    这个调度器时用于I/O操作。它基于根据需要,增长或缩减来自适应的线程池。由于它专用于I/O操作,所以并不是RxJava的默认方法;正确的使用它是由开发者决定的。重点需要注意的是线程池是无限制的,大量的I/O调度操作将创建许多个线程并占用内存。

  • .computation()

    这个是计算工作默认的调度器,它与I/O操作无关。它也是许多RxJava方法的默认调度器:buffer(), debounce(), delay() , interval(), sample(), skip()。

  • .immediate()

    这个调度器允许你立即在当前线程执行你指定的工作。它是timeout(),timeInterval(),以及timestamp()方法默认的调度器。

  • .newThread()

    这个调度器为指定任务启动一个新的线程。

  • .trampoline()

    当我们想在当前线程执行一个任务时,并不是立即,我们可以用.trampoline()将它入队。这个调度器将会处理它的队列并且按序运行队列中每一个任务。它是repeat()和retry()方法默认的调度器。

RxAndroid模块包含RxJava的Android特定的绑定代码。它给RxJava添加了一些类,用于帮助在Android应用中编写响应式(reactive)的组件。它提供了一个可以在给定的Android Handler上调度Observable的调度器 Scheduler,特别是在UI主线程上 AndroidSchedulers.mainThread()。

上面提到了几种线程调度器,可以让开发者在不同的线程执行不同的事件,那么如何指定和切换线程呢?RxJava提供了两个方法subscribeOn和observeOn,前者可以指定Observable事件产生和变换处理的线程,后者可以指定订阅者所在的线程,假如事件是一个耗时任务,完全可以通过subscribeOn指定为计算线程或者子线程,然后再通过observeOn切换Android主线程,即可在订阅者回调方法中操作UI视图。

看一个具体的例子吧。

Observable.just("").subscribeOn(Schedulers.newThread()).map(s -> {for (PerformanceEntity.Components components : performanceEntity.components) {PerformanceSubmitEntity.Data submitData = new PerformanceSubmitEntity.Data();submitData.componentId = components.id;for (PerformanceEntity.Data data : performanceEntity.data) {if (data.componentId == components.id) {transferData(submitData, data);break;}}submitDataList.add(submitData);}return null;}).observeOn(AndroidSchedulers.mainThread()).subscribe(o -> {initPerformanceView();});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

在渲染视图之前需要处理大量的数据,那么就可以将Observable的线程切换至子线程,等负责的业务逻辑完成后再切换至UI线程,然后在subscribe中完成视图的渲染。这样即可以保证UI线程不会大量复杂的计算,也可以不用Handler、AsycTask等复杂的操作,代码清晰度也相对较高。

三、RxJava与Retrofit的结合

在Android开发中,网络请求往往是最耗时的,也是情况最复杂的,如果直接在UI线程进行网络请求,编译时就会报错,及时编译报错,运行时系统也会报ANR错误,所以网络请求必须在子线程完成。而网络请求结果一般又需要操作UI视图,所以返回结果的回调有必须在主线程,那么上面提到的方法就可以完美解决这个问题。

网络请求的返回结果一般都是json格式,如果返回值为原始的字符串,那么就需要调用放每次都要进行json至JavaBean的转换,有的时候我们只关心返回结果中的一部分数据,那么就还需要在返回结果中再次对数据进行筛选,还有情况是我们只关心满足一定条件的数据,那么这些需求如果用RxJava来实现就变得异常简单。有关Retrofit详细用法,以及如何将返回结果切换成RxJava处理模式,可以阅读Retrofit用法详解这篇文章,下面直接看示例:

 showProgressBar();messageService.messageList(msgType, PAGE_INDEX, PAGE_SIZE).compose(new DefaultTransformer<>(getActivity())).map(messageListResponse -> messageListResponse.data).flatMap(messageListEntity -> Observable.from(messageListEntity)).filter(messageEntity.id > 10).subscribe(new Subscriber<MessageEntity>() {@Overridepublic void onCompleted() {dismissProgressBar();refreshLayout.setRefreshing(false);}@Overridepublic void onError(Throwable e) {dismissProgressBar();refreshLayout.setRefreshing(false);}@Overridepublic void onNext(MessageEntity messageEntity) {updateView(messageEntity);}});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • DefaultTransformer主要实现线程的切换以及错误消息的统一处理,一般来说服务端接口返回的数据格式都比较固定,会有code、message、data,其中code只是正确或者错误类型,message返回正确或者错误日志,data则是业务数据的存放地,那么就可以在DefaultTransformer中统一判断code值,如果是请求出错,那么直接将异常抛给onError回调方法。
  • map中实现的功能就是上文提到的调用方只关心data中的数据,而不关心code和message,那么就可以通过map方法直接将data中的数据传递给订阅者。
  • 如果我们想将返回值List逐条处理,一般的做法就是直接for循环,这里用到了flatMap,就是将messageListEntity通过Observable的from方法重新拆分成更细粒度的MessageEntity,而订阅者得到也就是MessageEntity。
  • filter方法就是通过布尔表达式筛选出符合条件的数据,上述例子中就是将id值大于10的MessageEntity筛选出来。

有关Observable的compose、map、from、flatMap、filter等方法可以参考ReactiveX官方教程,中文环境下可以参考给Android开发者的RxJava详解

这篇关于RxJava和Retrofit的介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1043936

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

Java中的.close()举例详解

《Java中的.close()举例详解》.close()方法只适用于通过window.open()打开的弹出窗口,对于浏览器的主窗口,如果没有得到用户允许是不能关闭的,:本文主要介绍Java中的.... 目录当你遇到以下三种情况时,一定要记得使用 .close():用法作用举例如何判断代码中的 input

Spring Gateway动态路由实现方案

《SpringGateway动态路由实现方案》本文主要介绍了SpringGateway动态路由实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录前沿何为路由RouteDefinitionRouteLocator工作流程动态路由实现尾巴前沿S