Android笔记(十八):面向Compose组件结合Retrofit2和Rxjava3实现网络访问

一、Retrofit2

Square公司推出的Retrofit2库(https://square.github.io/retrofit/),改变了网络访问的方式。它实现了网络请求的封装。Retrofit库采用回调处理方式,使得通过接口提交请求和相应的参数的配置,就可以获得对应的响应,并可以将响应获得的数据解析成特定的数据格式,例如将JSON数据解析成对象。
Retrofit访问网络资源的流程:
在这里插入图片描述

二、RxJava3

RxJava3(https://github.com/ReactiveX/RxJava)是响应式编程(Reactive Extensions)的java实现,它基于观察者模式的实现了异步编程接口。RxJava库通过使用可观察的序列来组成异步和基于事件的程序。
在这里插入图片描述

Observable可观察

即是一个主题,可以表示任何对象,它可以从数据源中获得数据或者其他的状态值。Observable对象发出数据流。只要有观察者开始接受,Observable就会提供数据,发出数据流。可观察者可以有多个订阅者。
在RxJava3中常见的可观察流如下表所示:

说明
io.reactivex.rxjava3.core.Flowable0…N流,支持响应式流和背压按照onSubscribe onNext (onError 或onComplete)属性执行,其中onNext可以执行多次,onError和onComplete是互斥的。
io.reactivex.rxjava3.core.Observable0…N流,不支持背压按照onSubscribe onNext (onError或onComplete)的顺序执行,onNext可以执行多次,onError与onComplete是互斥的。

Operator操作符

承担了对 Observable 可观察对象发出的事件进行修改和变换。每个Operator操作实际上是一个方法/函数,Observable对象作为输入参数,对于Observable对象发射的每一项数据,它会将在Operator方法/函数中应用这些数据,然后将处理结果以Observable对象形式返回。因此返回的是另外一个Observable对象。这个Observable对象可以继续向后发射或结束。

操作符Operator可以有若干个,形式如下:

dataSource.operator1()
.operator2()
.operator3()

这些操作符之间构成了上下流的关系。

Observer观察者

Observer观察者订阅可观察Observable对象的序列数据,并对可观察对象的每一项做出反应。观察者负责处理事件,它是事件的消费者。每当关联的Observable发出数据时,通知观察者。观察者一个接一个地处理数据。

背压策略

由于可观察者(Observable)和观察者(Observer)是在不同线程中分别实现发送数据和接受数据。由于不同线程中处理的时间伴随着问题的复杂度,会导致二者处理数据的速度出现不同。如果被观察者对象发射的数据的速度远远快于观察者对象处理数据的速度的话,会将数据放入到缓存暂存或者直接放弃这些数据。这两种方法的处理都有不妥之处。因此,需要制定“背压(Back Pressure)”策略,来解决二者在异步场景下,被观察者发射数据和观察者处理数据速度不一致的问题。因此,通常所说的背压是在异步环境下,控制流速的一种策略。常见的背压策略方式如下表所示:

背压策略说明
MISSING表示通过 create 方法创建的 Flowable 没有指定背压策略,不会对通过 OnNext 发射的数据做缓存或丢弃处理,下游必须处理操作符
ERROR发生背压,会发送MissingBackpressureException信号,以免下游不能消费继续。
BUFFER发生背压,会缓存数据,直至下游消化数据完成
DROP发生背压,会如果下游不能继续消费数据,将最近发射的值丢弃

三、网络访问处理实例

假设已经有网络资源 http://127.0.0.1:5000/json/students.json(也可以写成:http://localhost:5000/json/students.json),访问的内容如下所示:
在这里插入图片描述
在下面的例子中,将结合Retrofit2+RxJava3+Compose组件实现对上述资源的访问,并以列表的方式显示。运行结果类似下图:
在这里插入图片描述

1.AndroidManifest.xml配置网络访问

要访问网络需要设置互联网的访问权限,以及在应用中设置明文访问许可:

<uses-permission android:name="android.permission.INTERNET" />
<applicationandroid:usesCleartextTraffic="true" ...>
</application>

2.增加依赖

在项目模块的build.gradle.kt中增加如下依赖:

//retrofit框架
implementation ‘com.squareup.retrofit2:retrofit:2.9.0’
implementation ‘com.squareup.retrofit2:converter-gson:2.9.0’

//增加RxJava库的依赖
implementation “io.reactivex.rxjava3:rxjava:3.1.5”

//增加在Android对RxJava库的支持
implementation ‘io.reactivex.rxjava3:rxandroid:3.0.2’

//增加Retrofit支持RxJava3的CallAdapter
implementation ‘com.squareup.retrofit2:adapter-rxjava3:2.9.0’

implementation “androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1”

也可以根据最新的版本重新调整版本号。

3.定义实体类

data class Student(val id:String,
val name:String,
val gender:String,
val age:Int)

4.定义网络访问

(1)定义网络服务访问接口

interface StudentService{@GET("students.json")fun getStudents(): Flowable<List<Student>>
}

表示访问students.json资源获取一个RxJava3的Flowable可观察者对象。这个可观察者对象封装了包含学生记录的列表。

(2)定义网络服务创建类

object StudentServiceCreator{private val urlStr="http://10.0.2.2:5000/json/"private val retrofit = Retrofit.Builder().baseUrl(urlStr).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava3CallAdapterFactory.create()).build()fun <T> createService(serviceClass:Class<T>):T = retrofit.create(serviceClass)
}

Web服务器是本地服务器,由于移动模拟器的127.0.0.1已经被占用,因此要在移动端访问本地服务器,可以通过10.0.2.2来访问。
定义Retrofit对象,并在该对象中设置了解析JSON数据的转换对象和并发处理的适配器。

5.定义定义视图模型

定义视图模型,调用的网络访问处理的相关类,获取网络资源。

class StudentViewModel: ViewModel() {private val students:SnapshotStateList<Student> = mutableStateListOf()private val creator  = StudentServiceCreator.createService(StudentService::class.java)fun doNetwork(urlStr:String){creator.getStudents().observeOn(AndroidSchedulers.mainThread()).subscribe{it:List<Student>->if(students.isEmpty()){students.addAll(it)}}}fun getData() = students
}

6.定义界面

(1)定义列表的显示学生记录单项的可组合函数

@Composable
fun StudentItemCard(student: Student){Card(modifier = Modifier.fillMaxWidth().wrapContentHeight().padding(5.dp),elevation = CardDefaults.cardElevation(defaultElevation = 5.dp),colors = CardDefaults.cardColors(containerColor = Color.Blue,contentColor = Color.White)){Column(modifier= Modifier.fillMaxWidth().wrapContentHeight().padding(5.dp)){Text(text = "${student.id}",fontSize = 24.sp)Row(modifier = Modifier.padding(15.dp)){Text(text = "${student.name}",fontSize = 24.sp)Spacer(modifier = Modifier.padding(5.dp))Text(text = "${student.gender}",fontSize = 24.sp)Spacer(modifier = Modifier.padding(5.dp))Text(text = "${student.age}",fontSize = 24.sp)}}}
}

(2)定义学生记录的列表

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen(stuVM: StudentViewModel = viewModel()){var students = stuVM.getData()val displayState = remember{ mutableStateOf(false) }Scaffold(floatingActionButton = {FloatingActionButton(onClick = {displayState.value = true//访问网络资源stuVM.doNetwork("http://10.0.2.2:5000/json/students.json")//获取学生记录students = stuVM.getData()}) {Icon(Icons.Filled.Refresh,contentDescription = null)}}){Column(horizontalAlignment = Alignment.CenterHorizontally){Text(modifier = Modifier.fillMaxWidth(),text = "学生记录列表",textAlign = TextAlign.Center,fontSize = 28.sp)if(displayState.value){LazyColumn{items(students){it: Student ->StudentItemCard(student = it)}}}}}
}

7.定义主活动MainActivity

在主活动中调用界面

class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {Ch09_DemoTheme {// A surface container using the 'background' color from the themeSurface(modifier = Modifier.fillMaxSize(),color = MaterialTheme.colorScheme.background) {MainScreen()}}}}
}

参考文献

陈轶 第8章 Android网络应用《Android移动应用开发(微课版)》P258-P293 清华大学出版社

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

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

相关文章

安装2023最新版Java SE 21.0.1来开发Java应用程序

安装2023最新版Java SE 21.0.1来开发Java应用程序 Install the latest version of Java SE 21.01 to Develop Java Applications By JacksonML 本文简要介绍如何下载和安装2023年最新版Java Development Kit (简称JDK&#xff0c;即Java开发工具包标准版&#xff09;21.0.1&…

开发人员必须掌握的几个高级命令

xargs命令 在平时的使用中,我认为 xargs 这个命令还是较为重要和方便的。我们可以通过使用这个命令,将命令输出的结果作为参数传递给另一个命令。 比如说我们想找出某个路径下以 .conf 结尾的文件,并将这些文件进行分类,那么普通的做法就是先将以 .conf 结尾的文件先找出…

通过51单片机控制SG90舵机按角度正反转转动

一、前言 本文介绍如何通过51单片机控制SG90舵机实现角度的正反转转动。SG90舵机是一种常用的微型舵机&#xff0c;具有体积小、重量轻、结构简单等特点&#xff0c;被广泛应用于机器人、遥控模型和各种自动控制系统中。 使用51单片机&#xff08;STC89C52&#xff09;作为控…

RPM包管理_YUM

8.1 RPM包管理 8.1.1 RPM概述 RPM Package Manager (原Red Hat Package Manager&#xff0c;现在是一个递归缩写&#xff09; ​ 由Red Hat公司提出&#xff0c;被众多 Linux 发行版所采用也称二进制( binary code) 无需编译,可以直接使用 ​ 无法设定个人设置&#xff0c;开…

在 Windows PC 上轻松下载并安装 FFmpeg

FFmpeg 是一种开源媒体工具&#xff0c;可用于将任何视频格式转换为您需要的格式。该工具只是命令行&#xff0c;因此它没有图形、可点击的界面。如果您习惯使用常规图形 Windows 程序&#xff0c;安装 FFmpeg 一开始可能看起来很复杂&#xff0c;但不用担心&#xff0c;它;很简…

【探索评估】记录小车运动轨迹,并在 rviz 上显示

本文主要是参考的博客&#xff1a;ROS 移动机器人运动轨迹记录&#xff0c;并发布在rviz上 但是由于订阅的话题不一样&#xff0c;在这里记录一下 在进行自主探索的时候将小车移动过程中的消息记录在 txt 或是 csv 文件中 在此记录的是小车的 /odom 消息&#xff0c;并且只记录…

2023-12-14 二叉树的最大深度和二叉树的最小深度以及完全二叉树的节点个数

二叉树的最大深度和二叉树的最小深度以及完全二叉树的节点个数 104. 二叉树的最大深度 思想&#xff1a;可以使用迭代法或者递归&#xff01;使用递归更好&#xff0c;帮助理解递归思路&#xff01;明确递归三部曲–①确定参数以及返回参数 ②递归结束条件 ③单层逻辑是怎么样…

Leetcode—172.阶乘后的零【中等】

2023每日刷题&#xff08;六十&#xff09; Leetcode—172.阶乘后的零 算法思想 实现代码 int trailingZeroes(int n) {int ans 0;for(int i 5; i < n; i 5) {for(int j i; j % 5 0; j / 5) {ans;}}return ans; }运行结果 之后我会持续更新&#xff0c;如果喜欢我的文…

郝斌C语言自学教程笔记

赫斌C语言——笔记目录 c语言编程预备知识流程控制函数变量指针结构体位运算符 前段时间康哥看我C语言基础不牢,推荐我学习郝斌老师的C语言课程&#xff0c;花2周看完之后发现确实是目前所看的C语言课程中最好的&#xff0c;不仅非常适合入门&#xff0c;而且对即使学了几年C语…

2021年数维杯国际大学生数学建模B题极端降雨的定量分析求解全过程文档及程序

2021年数维杯国际大学生数学建模 B题 极端降雨的定量分析 原题再现&#xff1a; 近两年来&#xff0c;我国河南、陕西、湖北等地遭遇了极为罕见的暴雨。与此同时&#xff0c;北方一些城市遭遇了历史上罕见的暴风雪。这些暴雨和降雪对当地人民的生命、安全和财产构成严重威胁。…

基于ssm点餐平台系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本点餐平台系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&am…

生物制品行业分析:预计2029年将达到9704亿元

生物制品是由糖、蛋白质、核酸或该等物质的复杂组合组成并采用生物方法及来源生产的医药产品&#xff0c;生物制品也可以是细胞及组织等活体。生物制品的主要类型包括抗体、融合蛋白、ADC、重组蛋白、疫苗、基因疗法及细胞疗法。 预防用生物制品是指为预防、控制疾病的发生、流…