当前位置: 首页 > news >正文

12.1 Android中协程的基本使用

文章目录

  • 前言
  • 1、导入依赖
  • 2、使用协程获取服务器中的数据
    • 2.1 定义请求回调结果的数据类
    • 2.2 网络请求
  • 3、网络回调结构
  • 4、通过ViewModel处理网络请求数据

前言

在使用协程的时候一直没有一个具体的概念,只知道协程能够使得异步操作等同于同步操作,且不会造成线程阻塞,且第一次使用协程是根据前辈的代码修改而学会的,没有一个规范性的思维,通过查看官方资料将协程的使用重新梳理一遍,一个简单,不麻烦的做法。

1、导入依赖

选择依赖的方式主要分为两种,查看创建项目的时候中Build configuration language的选项选择的某一项,根据项目来选择

Groovy:

dependencies {implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
}

kotlin:

dependencies {implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9")
}

2、使用协程获取服务器中的数据

目的: 防止直接在UI线程中进行网络请求出现线程阻塞,导致应用程序无响应(ANR)

Dispatchers.IO:
用于执行I/O操作,如读写文件、访问数据库等。
这个调度器会尝试在后台线程池中执行I/O密集型任务,从而避免阻塞主线程

Dispatchers.Main:
用于在Android的主线程(UI线程)上执行协程。
这个调度器确保与UI相关的操作(如更新UI元素)在主线程上执行。
在非Android平台上(如桌面应用或纯Kotlin项目),Dispatchers.Main 可能不可用或行为不同。

Dispatchers.Default:
用于执行计算密集型任务。可用于执行网络请求,获取服务器数据
这个调度器使用共享的后台线程池来执行协程,从而优化CPU资源的利用。
它是默认的调度器,如果你没有为协程指定调度器,那么它将使用 Dispatchers.Default。

Dispatchers.Unconfined:
不绑定到任何特定的线程
协程在哪个线程上启动,它就会在那个线程上继续执行,直到遇到挂起点(如 suspend 函数调用)。
一旦协程挂起并恢复,它可能会在任何线程上继续执行,这取决于挂起函数的实现。

通常不建议在生产代码中使用 Dispatchers.Unconfined,因为它可能导致难以追踪的线程安全问题。
用法:

// 创建一个协程作用域(通常是在ViewModel、Activity或Fragment中)
val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)// 在协程作用域中启动一个协程
coroutineScope.launch(Dispatchers.IO) {// 执行I/O操作
}

2.1 定义请求回调结果的数据类

sealed 关键字
sealed 关键字用于定义一个密封类(sealed class),用于控制子类的个数,只接受子类在密封类的同一个文件中声明,或者作为密封类的嵌套类。

有助于改进when表达式,当使用密封类的时候,编译器会确保when表达式覆盖所有可能得子类,如果没有覆盖的话,则会出现报错的提醒,这有助于提高代码的健壮性和可维护性。

sealed class Result<out R> {data class Success<out T>(val data: T) : Result<T>()data class Error(val exception: Exception) : Result<Nothing>()
}

2.2 网络请求

为了防止主线程调用 makeLoginRequest 后出现阻塞界面情况。可以使用协程库中的 withContext() 函数将协程的执行操作移至其他线程,在其中执行耗时的网络请求操作

class LoginRepository(private val responseParser: LoginResponseParser) {private const val loginUrl = "https://example.com/login"suspend fun makeLoginRequest(jsonBody: String): Result<LoginResponse> {return withContext(Dispatchers.IO) {// Blocking network request codeval url = URL(loginUrl)(url.openConnection() as? HttpURLConnection)?.run {requestMethod = "POST"setRequestProperty("Content-Type", "application/json; utf-8")setRequestProperty("Accept", "application/json")doOutput = trueoutputStream.write(jsonBody.toByteArray())return Result.Success(responseParser.parse(inputStream))}return Result.Error(Exception("Cannot open HttpURLConnection"))}}
}

3、网络回调结构

假设请求回调的结构为:

{"success": true,"user": {"id": 123,"username": "exampleUser","email": "example@example.com"},"token": "some_jwt_token"}

为了适配并处理网络请求回调的数据,需要创建数据类,方便适配回调数据。

data class User(val id: Int,val username: String,val email: String
)data class LoginResponse(val success: Boolean,val user: User?,val token: String?
)

将网络请求返回的InoutStream通过LoginResponseParser 处理,读取返回的数据并进行处理,转为LoginResponse的数据。

import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReaderobject LoginResponseParser {private val gson = Gson()@Throws(JsonSyntaxException::class)fun parse(inputStream: InputStream): LoginResponse {return try {// 使用try-with-resources语句自动关闭BufferedReadergson.fromJson(BufferedReader(InputStreamReader(inputStream)).use {it.readText()}, LoginResponse::class.java)} catch (e: IOException) {// 处理IOException,例如记录日志或抛出运行时异常throw RuntimeException("Failed to read input stream", e)} catch (e: JsonSyntaxException) {// 处理JsonSyntaxException,例如记录日志或抛出运行时异常throw RuntimeException("Failed to parse JSON", e)}}
}

4、通过ViewModel处理网络请求数据

class LoginViewModel(private val loginRepository: LoginRepository
): ViewModel() {fun login(username: String, token: String) {viewModelScope.launch {val jsonBody = "{ username: \"$username\", token: \"$token\"}"val result = try {loginRepository.makeLoginRequest(jsonBody)} catch(e: Exception) {Result.Error(Exception("Network request failed"))}when (result) {is Result.Success<LoginResponse> -> // Happy pathelse -> Result.Error(Exception("reponse is error"))// Show error in UI}}}
}

想要了解更多协程相关的知识点,可以查看官网

相关文章:

12.1 Android中协程的基本使用

文章目录 前言1、导入依赖2、使用协程获取服务器中的数据2.1 定义请求回调结果的数据类2.2 网络请求 3、网络回调结构4、通过ViewModel处理网络请求数据 前言 在使用协程的时候一直没有一个具体的概念&#xff0c;只知道协程能够使得异步操作等同于同步操作&#xff0c;且不会…...

【黑马点评优化】2-Canel实现多级缓存(Redis+Caffeine)同步

【黑马点评优化】2-Canel实现多级缓存&#xff08;RedisCaffeine&#xff09;同步 0 背景1 配置MySQL1.1 开启MySQL的binlog功能1.1.1 找到mysql配置文件my.ini的位置1.1.2 开启binlog 1.2 创建canal用户 2 下载配置canal2.1 canal 1.1.5下载2.2 配置canal2.3 启动canal2.4 测试…...

php-fpm

摘要 php-fpm(fastcgi process manager)是PHP 的FastCGI管理器&#xff0c;管理PHP的FastCGI进程&#xff0c;提升PHP应用的性能和稳定性 php-fpm是一个高性能的php FastCGI管理器&#xff0c;提供了更好的php进程管理方式&#xff0c;可以有效的控制内存和进程&#xff0c;支…...

Python3测试开发面试题2

python的内存池机制 在Python中&#xff0c;内存管理是通过Python的内存管理器和C语言实现的&#xff0c;特别是依赖于CPython的实现。CPython使用一种名为“内存池”&#xff08;memory pool&#xff09;的技术来优化小对象&#xff08;如小整数、短字符串等&#xff09;的内…...

qt + opengl 给立方体增加阴影

在前几篇文章里面学会了通过opengl实现一个立方体&#xff0c;那么这篇我们来学习光照。 风氏光照模型的主要结构由3个分量组成&#xff1a;环境(Ambient)、漫反射(Diffuse)和镜面(Specular)光照。下面这张图展示了这些光照分量看起来的样子&#xff1a; 1 环境光照(Ambient …...

Webpack,Vite打包的理解

Webpack 和 Vite 都是现代前端开发中常用的构建工具&#xff0c;用于打包和优化项目代码。尽管它们的目标相似&#xff0c;但在设计理念、工作方式和适用场景上存在显著差异。 Webpack Webpack 是一个模块打包工具&#xff0c;主要用于将多个模块&#xff08;如 JavaScript、…...

Vue 3 30天精进之旅:Day 25 - PWA支持

一、引言 在前面的24天中&#xff0c;我们已经深入探讨了Vue 3的许多核心概念和高级特性。今天&#xff0c;我们将进入一个全新的领域——PWA&#xff08;Progressive Web App&#xff09;。PWA是一种现代Web应用程序的开发模式&#xff0c;它结合了Web和原生应用的优点&#…...

机器学习-生命周期

假如一个用户向银行申请贷款&#xff0c;银行该如何对这个用户进行评估?很明显&#xff0c;银行首先需要调查清楚该用户的资金储备情况和信用历史等&#xff0c;然后再决定是否向其放款。 整个机器学习生命周期如下图所示&#xff1a; 1、定义问题 在使用机器学习中的术语表…...

大道至简 少字全意 易经的方式看 缓存 mybatis缓存 rendis缓存场景 案例

目录 介绍 mybatis缓存 一级缓存 1.是什么 2.特点 3.场景 mybatis 二级缓存 1.是什么 2.特点 3.配置步骤 注意 一级缓存问题 二级缓存问题 扩展 1.MyBatis集成 Redis 2.直接使用Redis redis 缓存 一、String 字符串 二、Llst 列表 三、Hash 哈希 四、Set…...

如何使用 Flutter DevTools 和 PerformanceOverlay 监控性能瓶颈

使用 Flutter DevTools 和 PerformanceOverlay 监控性能瓶颈&#xff1a;详细分析与实战 在开发 Flutter 应用时&#xff0c;性能问题可能会导致用户体验下降&#xff0c;比如页面卡顿、掉帧、内存泄漏等。为了定位和解决这些问题&#xff0c;Flutter 提供了强大的性能监控工具…...

TS中Any和Unknown有什么区别

在 TypeScript 中&#xff0c;any 和 unknown 都是顶级类型&#xff08;top types&#xff09;&#xff0c;表示可以是任何类型的值。但它们在使用和行为上有显著区别&#xff0c;主要体现在类型安全性和使用方式上。 1. any 类型 特点&#xff1a; any 是 TypeScript 中最宽松…...

【Mpx】-环境搭建项目创建(一)

一.概述 官方文档&#xff1a;https://mpxjs.cn/guide/basic/start.html mpxjs/cli文档: https://github.com/mpx-ecology/mpx-cli 二.脚手架安装&创建项目 2.1项目创建 //脚手架安装 npm i -g mpxjs/cli //创建Mpx项目 mpx create mpx-demo(项目名称) //安装依赖 np…...

PyQt加载UI文件

1.动态加载 import sys from PySide6 import QtCore,QtWidgets from PySide6.QtWidgets import * from PySide6.QtUiTools import QUiLoaderclass readfile(QWidget):def __init__(self):super().__init__()self.uiQUiLoader().load("test.ui",self) self.__c…...

Java面试第二山!《计算机网络》!

在 Java 面试里&#xff0c;计算机网络知识是高频考点&#xff0c;今天就来盘点那些最容易被问到的计算机网络面试题&#xff0c;帮你轻松应对面试&#xff0c;也方便和朋友们一起探讨学习。 一、HTTP 和 HTTPS 的区别 1. 面试题呈现 HTTP 和 HTTPS 有什么区别&#xff1f;在…...

Mysql基础语句

一、 MySQL语句 在熟悉安装及访问 MySQL 数据库以后&#xff0c; 接下来将学习使用 MySQL 数据库的基本操作&#xff0c;这也是在服务器运维工作中不可或缺的知识。 本节中的所有数据库语句均在“MySQL>”操作环境中执行 MySQL 是一套数据库管理系统&#xff0c;在每台 MySQ…...

连接池Java导包

目录 一、Java导包 二、 数据库连接池 1. 概述 2. 常见参数 3. 常见连接池 4. Druid连接池&#xff08;重点&#xff09; 核心功能&#xff1a; 使用方法&#xff1a; 导入依赖 配置连接池&#xff1a; 代码配置&#xff1a; 配置文件&#xff1a; 获取连接&#…...

一些耳朵起茧子的名词解释

1 web应用 1.1 web应用的概念 Web应用&#xff08;Web Application&#xff09; 是一种通过浏览器访问的软件程序&#xff0c;它运行在服务器上&#xff0c;用户通过网络&#xff08;如互联网或内网&#xff09;与它进行交互。与传统网站&#xff08;主要提供静态内容&#x…...

HBuilderX中,VUE生成随机数字,vue调用随机数函数

Vue 中可以使用JavaScript的Math.random() 函数生成随机数&#xff0c;它会返回 0 到 1 之间的浮点数&#xff0c; 如果需要0到1000之前的随机数&#xff0c;可以对生成的随机数乘以1000&#xff0c;再用js的向下取整函数Math.floor() 。 let randNum Math.random(); // 生成…...

C#发送邮件

基础调用类&#xff1a; public class EmailHelper{/// <summary>/// 发件人名称/// </summary>public string MailName { get; set; }/// <summary>/// 收件人/// </summary>public string MailTo { get; set; }/// <summary>/// 密送/// <…...

2025-2-19学习笔记 : this关键字,constructor结构体,class类

1、This关键字 在 JavaScript 中&#xff0c;this 是一个关键字&#xff0c;其指向取决于函数的调用方式。理解 this 的指向对于编写正确的代码至关重要。以下是 this 在不同情况下的指向规则&#xff1a; 1. 全局函数调用 当函数在全局作用域中被调用时&#xff0c;this 指向…...

Sunshine游戏串流:5分钟搭建你的个人云游戏服务器

Sunshine游戏串流&#xff1a;5分钟搭建你的个人云游戏服务器 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 想要在任何设备上流畅玩转PC游戏大作&#xff1f;Sunshine作为一款强…...

如何用Bedrock Launcher解锁Minecraft基岩版的完整潜力?Windows 10启动器终极指南

如何用Bedrock Launcher解锁Minecraft基岩版的完整潜力&#xff1f;Windows 10启动器终极指南 【免费下载链接】BedrockLauncher 项目地址: https://gitcode.com/gh_mirrors/be/BedrockLauncher 还在为Minecraft基岩版的功能限制感到烦恼吗&#xff1f;想要像Java版那样…...

AI Agent Harness Engineering 成本与收益的真相:企业投入产出比全景分析与 ROI 计算方法论

AI Agent Harness Engineering 成本与收益的真相&#xff1a;企业投入产出比全景分析与 ROI 计算方法论副标题&#xff1a;从盲目跟风到数据驱动决策——拆解百万到十亿级Agent项目的真实投入、可量化收益与可持续增长模型第一部分&#xff1a;引言与基础 (Introduction & …...

自托管开源联系人管理系统:数据主权、vCard标准与API驱动架构实践

1. 项目概述&#xff1a;一个面向未来的联系人管理解决方案最近在整理一个老项目时&#xff0c;我重新审视了“Aquariosan/veyra-contacts”这个仓库。这不仅仅是一个简单的通讯录应用&#xff0c;它更像是一个理念的实践场&#xff0c;探讨在数据主权意识日益增强的今天&#…...

保姆级教程:在Ubuntu 20.04上用Geth 1.10.5部署你的第一个HelloWorld合约(含Remix编译与ABI处理)

从零到一&#xff1a;Ubuntu 20.04环境下Geth 1.10.5智能合约全流程实战 当清晨的第一缕阳光透过窗帘缝隙洒在Ubuntu终端窗口上时&#xff0c;你可能正在为人生中第一个智能合约的部署而兴奋不已。本文将带你完整走通从Solidity编码到合约交互的每个环节&#xff0c;特别针对Ge…...

Awoo Installer 终极指南:3种安装方式全解析,Switch游戏安装从未如此简单

Awoo Installer 终极指南&#xff1a;3种安装方式全解析&#xff0c;Switch游戏安装从未如此简单 【免费下载链接】Awoo-Installer A No-Bullshit NSP, NSZ, XCI, and XCZ Installer for Nintendo Switch 项目地址: https://gitcode.com/gh_mirrors/aw/Awoo-Installer A…...

D3KeyHelper:暗黑破坏神3玩家的免费终极按键助手,10分钟上手告别手酸

D3KeyHelper&#xff1a;暗黑破坏神3玩家的免费终极按键助手&#xff0c;10分钟上手告别手酸 【免费下载链接】D3keyHelper D3KeyHelper是一个有图形界面&#xff0c;可自定义配置的暗黑3鼠标宏工具。 项目地址: https://gitcode.com/gh_mirrors/d3/D3keyHelper 还在为暗…...

别再手动做PPT了!用Python-pptx库,5分钟搞定周报/月报自动化生成

用Python-pptx实现周报自动化&#xff1a;从模板设计到数据绑定的完整指南 每周五下午&#xff0c;市场部的张磊总要面对同样的噩梦&#xff1a;从十几个Excel表格中复制数据&#xff0c;粘贴到PPT模板里&#xff0c;调整格式到深夜。直到他发现了一个秘密武器——python-pptx。…...

终极指南:如何在Windows电脑上免费接收iPhone和iPad的AirPlay 2投屏

终极指南&#xff1a;如何在Windows电脑上免费接收iPhone和iPad的AirPlay 2投屏 【免费下载链接】airplay2-win Airplay2 for windows 项目地址: https://gitcode.com/gh_mirrors/ai/airplay2-win 你是否曾经羡慕Mac用户能够轻松将iPhone或iPad屏幕投射到电脑上&#xf…...

nli-MiniLM2-L6-H768一文详解:蕴含/矛盾/中立三分类服务落地

nli-MiniLM2-L6-H768一文详解&#xff1a;蕴含/矛盾/中立三分类服务落地 1. 认识自然语言推理服务 自然语言推理(Natural Language Inference, NLI)是自然语言处理中的一项基础任务&#xff0c;它能够判断两段文本之间的逻辑关系。nli-MiniLM2-L6-H768是一个轻量级但功能强大…...