在Android中,如何通过Kotlin协程处理多个API调用

news/2024/5/19 13:21:03

在Android中,如何通过Kotlin协程处理多个API调用

在Android开发中,如何使用Kotlin协程处理多个API调用的示例呢?假设我们已经对Kotlin协程有了一定的了解,包括定义、简单用例和示例等。现在,让我们来看一些真实的Android场景或用例。我们将从一个关于协程作用域的简单问题开始,比如生命周期作用域。

协程问题

问题 #1:如果我们在协程生命周期作用域中运行任何内容而没有提及分发器会发生什么呢?

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)lifecycleScope.launch {val s1 = someTask()Log.d(TAG, s1)}
}suspend fun someTask(): String {// 我不相信你,给我看看当前线程Log.d(TAG, "当前运行的线程 ${Thread.currentThread().name}")delay(2000) // 模拟延迟以进行演示return "任务的结果"
}

问题 #2

如果它在主线程中运行,那么…
如果我们在协程挂起函数调用之后在作用域外打印一些东西到TextView中会发生什么?

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)lifecycleScope.launch {val s1 = someTask()Log.d(TAG, s1)}binding.myTextView.text = "挂起函数调用之后"
}

问题#3

更复杂一些,我们加一个while循环,那么结果会怎么样呢?会不会导致UI线程出现ANR呢?想要知道答案,请自行运行代码看看结果。

lifecycleScope.launch {val s1 = someTask()Log.d(TAG, s1)
}
binding.myTextView.text = "挂起函数调用之后"
while (true) {//假设这是模拟UI任务,比如动画或进度旋转,正在进行的UI//我们的主线程现在应该始终忙碌Log.d(TAG, "我是UI模拟任务")
}

解决方案

用例 #1

我们必须进行两个API调用,第一个API调用将返回一个Auth令牌。然后我们必须使用这个令牌调用第二个API。
简而言之,我们的第二个API依赖于我们第一个API调用的结果。

lifecycleScope.launch {val token  = firstApiCall()Log.d(TAG, "token是 $token")val result = secondApiCall(token)Log.d(TAG, "结果是 $result")
}suspend fun firstApiCall(): String {// 执行API调用1delay(2000) // 模拟延迟以进行演示return "1234"
}suspend fun secondApiCall(token: String): String {// 执行API调用2delay(2000) // 模拟延迟以进行演示return "API调用结果 $token"
}

就这样了?是的,就是这样!
但等等!这并不是一个真实的使用ViewModel和MVVM模式进行API调用的示例。
好的,我们来看一些真实的代码。

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.delay
import kotlinx.coroutines.launchclass TestViewModel: ViewModel() {fun secondApiCall() {viewModelScope.launch {try {val token  = getMyToken(isSuccess = true)Log.d(TAG, "token is $token")//Now make your second API call here using this token//repository.getMyData(token)} catch (ex: Exception) {}}}private suspend fun getMyToken(isSuccess: Boolean): String? {val deferred = CompletableDeferred<String?>()if (isSuccess) {delay(1000)deferred.complete("1234")} else {delay(1000)deferred.completeExceptionally(Throwable("Error"))}return deferred.await()}
}

不必进行两次API调用,因为第二次调用依赖于第一次调用!你可以直接调用secondApiCall()函数,它会获取你的令牌。它会等待认证令牌返回,然后使用该令牌调用实际的API。就是这样!

用例 #2

再次,我们必须进行两次API调用,这次我们需要同时获取两个API结果。如果我们只得到一个结果,那么我们无法在UI中显示它,也无法设置RecyclerView Adapter。

lifecycleScope.launch {//viewModel.secondApiCall()val result = firstApiCall()val result2 = secondApiCall()Log.d(TAG, "$result and $result2")
}// Assume you have some suspend functions for API calls
suspend fun firstApiCall(): String {// Perform API call 1delay(2000) // Simulating a delay for demonstrationreturn "I am first call"
}suspend fun secondApiCall(): String {// Perform API call 2delay(2000) // Simulating a delay for demonstrationreturn "I am second call"
}

就这样?并不完全是。因为它们将按顺序运行,也就是同步运行,所以完成这两个调用将需要4秒钟。

现在我们没有任何依赖关系,那么为什么要浪费时间呢?

让我们看看最终优化的代码!

lifecycleScope.launch {val result = async { firstApiCall() }val result2 = async { secondApiCall() }Log.d(TAG, "${result.await()} and ${result2.await()}")
}

现在你已经节省了2秒钟。请记住,这是每个Android开发者面试都会遇到的一个非常常见的问题。即使他们不问,你也可以提供这些示例来展示你的知识和专业能力。
感谢您的阅读!您可以关注我获取更多信息。
如果您想知道我在哪里,可以查看我的个人资料中的关于部分。


http://www.mrgr.cn/p/57768157

相关文章

ROS仿真小车与SLAM

ROS仿真小车与SLAM ROS中机器小车的仿真实验一、建立模型1.创建功能包导入依赖&#xff1a;创建urdf,launch文件&#xff1a; 2.可视化 二、添加雷达传感器1.编写xacro文件2.集成launch文件3.添加摄像头和雷达传感器my_camera.urdf.xacro文件&#xff1a;my_laser.urdf.xacro文…

Docker新建容器 修改运行容器端口

一、修改容器的映射端口 项目需求修改容器的映射端口 二、解决方案 停止需要修改的容器 修改hostconfig.json文件 重启docker 服务 启动修改容器 三、方案 目前正在运行的容器 宿主机的89 端口 映射 容器端口80 3.1测试环境中新建nginx服务 docker run -itd --n…

【目标检测】Deformable DETR

一、前言 论文&#xff1a; Deformable DETR: Deformable Transformers for End-to-End Object Detection 作者&#xff1a; SenseTime Research 代码&#xff1a; Deformable DETR 特点&#xff1a; 提出多尺度可变形注意力 (Multi-scale Deformable Attention) 解决DETR收敛…

被问了n遍的小程序地理位置权限开通方法

小程序地理位置接口有什么功能&#xff1f; 在平时我们在开发小程序时&#xff0c;难免会需要用到用户的地理位置信息的功能&#xff0c;小程序开发者开放平台新规要求如果没有申请开通微信小程序地理位置接口( getLocation )&#xff0c;但是在代码中却使用到了相关接口&#…

顺序栈的实现

顺序栈的模板/******************************************************************************************************** * * file name: Zqh_栈实现.c * author : keyword2024@163.com * date : 2024/05/05 * function : 该程序实现顺序栈元素的增删改查 * note :…

双向循环链表的实现

双向循环链表的模板/******************************************************************************************************** * * file name: Zqh_链表.c * author : keyword2024@163.com * date : 2024/05/05 * function : 链表的增删改查 * note : 模板 * * Co…

Rust语言系统编程实战(小北学习笔记)

前言 进入大学以来&#xff08;计算机应用技术——大数据方向&#xff09;&#xff0c;就像很多程序猿&#x1f412;一样&#xff0c;小北开始每学期学习一种新的编程语言。通过学习另一个编程语言&#xff0c;可以了解很多规范和规则&#xff0c;并得到了一些想法&#xff0c;…

用龙梦迷你电脑福珑2.0做web服务器

用龙梦迷你电脑福珑2.0上做web服务器是可行的。已将一个网站源码放到该电脑&#xff0c;在局域网里可以访问网站网页。另外通过在同一局域网内的一台windows10电脑上安装花生壳软件&#xff0c;也可以在外网访问该内网服务器网站网页。该电脑的操作系统属于LAMP。在该电脑上安装…

【Linux网络编程】自定义协议+HTTP协议

【Linux网络编程】自定义协议HTTP协议 目录 【Linux网络编程】自定义协议HTTP协议协议定制&#xff0c;序列化和反序列化应用层中的HTTP认识URL&#xff08;网址&#xff09;urlencode和urldecodeHTTP协议格式使用telnet获取百度的根目录资源HTTP的方法表单 HTTP的状态码HTTP常…

工作感受月记(202405月)

2024年05月06号 新的一月工作天,旧事未清理,新事不停生。 今日工作事项: 1/ 来了一个新案例,apim stv1 升级到stv2的情况,客户需要noam同学来帮助建会议处理问题。 2/ 自己研究durable function的4001端口问题,证明确实是gRPC需要使用,用于 isolated process处理时候,进…

ROS 2边学边练(43)-- 利用GTest写一个基本测试(C++)

前言 在ROS&#xff08;Robot Operating System&#xff09;中&#xff0c;gtest&#xff08;Google Test&#xff09;是一个广泛使用的C测试框架&#xff0c;用于编写和执行单元测试。这些测试可以验证ROS节点、服务和消息等的正确性和性能。 如果我们需要在写的包中添加测试&…

RockChip Android13 NFC SL6320移植

环境:RK3568 Android13 一:驱动移植 1、驱动 将SL6320驱动代码拷贝至kernel-5.10/drivers/misc/sl6320/ 特殊说明:勿将驱动代码放置于kernel-5.10/drivers/nfc/目录下,会导致sl6320驱动生成设备节点时因/dev/nfc节点以创建而加载失败。 2、DTS 本次硬件设计电路走I2C协…

冲刺第三天

今天继续优化登录界面,寻找到了app的图标和想出了名字,

软件测试必问的33个面试题

1.你为什么选择软件测试行业 因为之前有了解软件测试这个行业&#xff0c;觉得他的发展前景很好。 2.根据你以前的工作经验描述一下软件开发、测试过程&#xff0c;由那些角色负责&#xff0c;你做什么 要有架构师、开发经理、测试经理、程序员、测试员。我在里面主要是负责所…

【MyBatis】深入解析MyBatis:高效操作数据库技术详解

&#x1f493; 博客主页&#xff1a;从零开始的-CodeNinja之路 ⏩ 收录文章&#xff1a;【MyBatis】深入解析MyBatis&#xff1a;高效操作数据库技术详解 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 动态SQL1. \<if>标签2. \<trim&…

Spring 当中的Bean 作用域

Spring 当中的Bean 作用域 文章目录 Spring 当中的Bean 作用域每博一文案1. Spring6 当中的 Bean的作用域1.2 singleton 默认1.3 prototype1.4 Spring 中的 bean 标签当中scope 属性其他的值说明1.5 自定义作用域&#xff0c;一个线程一个 Bean 2. 总结:3. 最后&#xff1a; 每…

KaiwuDB 解析器之语义解析

KaiwuDB 解析器介绍 解析器是数据库系统的重要组成部分之一&#xff0c;主要的功能是将客户端输入的 SQL 语句分解为语法单元&#xff0c;然后将这些语法单元转化成数据库内部可识别的数据结构&#xff0c;最终生成数据库可以执行的计划。 KaiwuDB 的一条 SQL 执行的整个生命…

全国33个省228189个矿产地位置分布数据,含经纬度坐标/CSV格式

全国矿产地分布&#xff08;2021版&#xff09; 数据来源&#xff1a; 全国矿产地数据库2021版 (ngac.org.cn) http://data.ngac.org.cn/mineralresource/index.html 数据获取方法&#xff1a;树谷资料库大全&#xff08;2024年4月19日更新&#xff09; 进入网站后&#xf…

线程池核心原理浅析

由于系统资源是有限的,为了降低资源消耗,提高系统的性能和稳定性,引入了线程池对线程进行统一的管理和监控,本文将详细讲解线程池的使用、原理。前言 由于系统资源是有限的,为了降低资源消耗,提高系统的性能和稳定性,引入了线程池对线程进行统一的管理和监控,本文将详细…

04-19 周四 GitHub CI 方案设计

04-19 周四 GitHub CI 方案设计 时间版本修改人描述2024年4月19日14:44:23V0.1宋全恒新建文档2024年4月19日17:22:57V1.0宋全恒完成部署拓扑结构的绘制和文档撰写 简介 需求 由于团队最近把代码托管在GitHub上&#xff0c;为解决推理、应用的自动化CI的需要&#xff0c;调研了…