Kotlin:runBlocking导致App应用出现ANR问题实例

runBlocking简介

runBlocking 是常规函数;
runBlocking 方法会阻塞当前线程来等待;
runBlocking 的主线程会一直 阻塞 直到 runBlocking 内部的协程执行完毕。

runBlocking导致App应用出现ANR问题实例的效果

点击页面上的 刷新按钮 调用 refreshByrunBlocking方法,此方法里模拟了等待30秒耗时操作,当点击 刷新按钮 等待3秒左右,点击 详情按钮,页面出现ANR弹框如下图所示
在这里插入图片描述

页面布局activity_test_anr_by_runblocking.xml代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/btn_refresh"android:layout_width="match_parent"android:layout_height="50dp"android:layout_marginLeft="20dp"android:layout_marginTop="60dp"android:layout_marginRight="20dp"android:gravity="center"android:onClick="onClick"android:text="刷新"android:textColor="@color/black"android:textSize="20sp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><Buttonandroid:id="@+id/btn_detail"android:layout_width="0dp"android:layout_height="50dp"android:layout_marginTop="60dp"android:gravity="center"android:onClick="onClick"android:text="详情"android:textColor="@color/black"android:textSize="20sp"app:layout_constraintLeft_toLeftOf="@+id/btn_refresh"app:layout_constraintRight_toRightOf="@+id/btn_refresh"app:layout_constraintTop_toBottomOf="@+id/btn_refresh" /><TextViewandroid:id="@+id/tv_detail"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_marginTop="60dp"android:onClick="onClick"android:textColor="@color/black"android:textSize="16sp"app:layout_constraintLeft_toLeftOf="@+id/btn_detail"app:layout_constraintRight_toRightOf="@+id/btn_detail"app:layout_constraintTop_toBottomOf="@+id/btn_detail"tools:text="用户信息" /></androidx.constraintlayout.widget.ConstraintLayout>

实体类:PsersonBean.kt代码

data class PsersonBean(val name: String, var moblie: String? = null)//至少有一个构造函数

TestANRByRunBlockingActivity.kt代码

package example.demo.kotlin.activityimport android.app.Activity
import android.os.Bundle
import android.view.View
import android.widget.TextView
import example.demo.kotlin.R
import example.demo.kotlin.bean.PsersonBean
import example.demo.kotlin.utils.LogUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlockingclass TestANRByRunBlockingActivity : Activity() {private lateinit var tv_detail: TextViewprivate var psersonBean: PsersonBeaninit {psersonBean = PsersonBean("测试用户01")}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_test_anr_by_runblocking)initView()}override fun onStart() {super.onStart()showData()}fun initView() {tv_detail = findViewById(R.id.tv_detail)}fun showData() {//使用lateinit var 延时初始化,这里安全起见,判断是否 isInitializedif (::tv_detail.isInitialized) {tv_detail.setText("$psersonBean")//注意,因为PsersonBean是 data class 类型 不需要重新toString 函数}}fun onClick(view: View) {when (view.id) {R.id.btn_refresh -> refreshByrunBlocking2()R.id.btn_detail -> detail()}}/*** 出现了ANR问题*/fun refreshByrunBlocking() {runBlocking(context = Dispatchers.IO) {LogUtil.i("开始执行 刷新 耗时操作了")delay(30000)//假设30秒,可以假设真实网络请求出现超时了,方便演示出现ANR问题psersonBean = PsersonBean("测试用户02")LogUtil.i("刷新 耗时操作结束")}LogUtil.i("刷新 耗时操作 事件执行完毕")showData()}/*** runBlocking里即使使用 async 也会出现ANR问题*/fun refreshByrunBlocking2() {runBlocking(context = Dispatchers.IO) {LogUtil.i("开始执行 刷新 耗时操作了")val psersonBean = async {delay(30000)//假设30秒,可以假设真实网络请求出现超时了,方便演示出现ANR问题PsersonBean("测试用户02")}LogUtil.i("刷新 耗时操作结束")}LogUtil.i("刷新 耗时操作 事件执行完毕")showData()}/*** 使用GlobalScope.launch ,没有出现ANR问题*/fun refreshByGlobalScopeLaunch() {GlobalScope.launch(context = Dispatchers.IO) {LogUtil.i("开始执行 刷新 耗时操作了")delay(30000)//假设30秒,可以假设真实网络请求出现超时了,方便演示出现ANR问题psersonBean = PsersonBean("测试用户02")LogUtil.i("刷新 耗时操作结束")withContext(Dispatchers.Main){//切换到主线程更新UIshowData()}}LogUtil.i("调用了 refreshByGlobalScopeLaunch 方法,没有阻塞当前线程")}fun detail() {LogUtil.i("执行了查看详情事件")psersonBean.moblie = "12345678901"showData()}
}

使用GlobalScope.launch解决ANR问题

点击页面上的 刷新按钮 调用 refreshByGlobalScopeLaunch方法,此方法里模拟了等待30秒耗时操作,当点击 刷新按钮 等待3秒左右,点击 详情按钮,页面数据正常显示如下图所示
在这里插入图片描述

刷新耗时操作结束,主线程更新UI
在这里插入图片描述

总结

  1. runBlocking主线程会一直 阻塞 直到 runBlocking 内部的协程执行完毕,执行长时间耗时操作会导致App应用出现ANR问题。
  2. runBlocking里即使使用 async 也会导致App应用出现ANR问题。
  3. GlobalScope.launch可以解决耗时操作App应用出现ANR问题,注意需要配合withContext(Dispatchers.Main)进行更新UI操作

推荐

Kotlin:协程基础

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

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

相关文章

【云原生-kubernetes系列】--kubernetes日志收集

1、ELK架构 1.1、部署ES集群 https://mirrors.tuna.tsinghua.edu.cn/elasticstack/apt/7.x/pool/main/e/elasticsearch/ 1、下载软件包 rootes-server1:~# wget https://mirrors.tuna.tsinghua.edu.cn/elasticstack/apt/7.x/pool/main/e/elasticsearch/elasticsearch-7.12.0-…

媒体播放器及媒体服务器软件Plex

什么是 Plex &#xff1f; Plex 是一套媒体播放器及媒体服务器软件&#xff0c;让用户整理在设备上的有声书、音乐、播客、图片和视频文件&#xff0c;并通过流式传输至移动设备、智能电视和电子媒体播放器上。Plex 可用于 Windows、Android、Linux、OS X和 FreeBSD。 在接触 N…

基于SpringBoot和Echarts的全国地震可视化分析实战

目录 前言 一、后台数据服务设计 1、数据库查询 2、模型层对象设计 3、业务层和控制层设计 二、Echarts前端配置 1、地图的展示 2、次数排名统计 三、最终结果展示 1、地图展示 2、图表展示 总结 前言 在之前的博客中基于SpringBoot和PotsGIS的各省地震震发可视化分…

Redis系列学习文章分享---第三篇(Redis快速入门之Java客户端--短信登录+session+验证码+拦截器+登录刷新)

目录 Redis的短信登录实战解析1. 短信登录-基于session实现短信登录的流程2. 短信登录-实现发送短信验证码功能3. 短信登录-实现短信验证码登录和注册功能4. 短信登录-实现登录校验拦截器5. 短信登录-隐藏用户敏感信息6. 短信登录-session共享的问题分析7. 短信登录-Redis代替s…

代码+视频,R语言使用BOOT重抽样获取cox回归方程C-index(C指数)可信区间

bootstrap自采样目前广泛应用与统计学中&#xff0c;其原理很简单就是通过自身原始数据抽取一定量的样本&#xff08;也就是取子集&#xff09;&#xff0c;通过对抽取的样本进行统计学分析&#xff0c;然后继续重新抽取样本进行分析&#xff0c;不断的重复这一过程N&#xff0…

使用MQTT.fx和自定义Client(Ubuntu上实现)测试MQTT服务器(EMQX )

目录 概述 1 配置EMQX做MQTT服务器 1.1 登录EMQX 1.2 配置EMQX 1.2.1 配置客户端认证 1.2.2 创建用户 2 测试MQTT服务器 2.1 配置MQTT.fx工具 2.2 连接MQTT服务器 3 使用MQTT.fx发布和订阅信息 3.1 在MQTT.fx上发布信息 3. 2 在MQTT.fx上订阅信息 4 Ubuntu上实现MQ…

(done 剩个什么 3/4 unigram frequency 的玩意儿没懂) word2vec 算法,计算 嵌入矩阵(CBOW, Skip-gram)随机梯度下降法 SGD 负采样方案

参考视频1&#xff1a;https://www.bilibili.com/video/BV1vS4y1N7mo/?vd_source7a1a0bc74158c6993c7355c5490fc600 &#xff08;讲的太浅了&#xff09; 参考视频2&#xff1a;https://www.bilibili.com/video/BV1s64y1P7Qm?p4&vd_source7a1a0bc74158c6993c7355c5490fc…

微信小程序-webview分享

项目背景 最近有个讨论区项目需要补充分享功能&#xff0c;希望可以支持在微信小程序进行分享&#xff0c;讨论区是基于react的h5项目&#xff0c;在小程序中是使用we-view进行承载的 可行性 目标是在打开web-view的页面进行分享&#xff0c;那就需要涉及h5和小程序的通讯问…

苹果Find My App用处多多,产品认准伦茨科技ST17H6x芯片

苹果发布AirTag发布以来&#xff0c;大家都更加注重物品的防丢&#xff0c;苹果的 Find My 就可以查找 iPhone、Mac、AirPods、Apple Watch&#xff0c;如今的Find My已经不单单可以查找苹果的设备&#xff0c;随着第三方设备的加入&#xff0c;将丰富Find My Network的版图。产…

【Leetcode每日一题】 递归 - 反转链表(难度⭐)(35)

1. 题目解析 题目链接&#xff1a;206. 反转链表 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 一、递归函数的核心任务 递归函数的主要职责是接受一个链表的头指针&#xff0c;并返回该链表逆序后的新头结点。递归…

复习C语言基础中的基础:C语言发展、C89 C99有何区别、C语言特点

参考《C程序设计&#xff08;第五版&#xff09;》&#xff08;谭浩强&#xff09;一书&#xff1a; 1. 发展、C89 C99 2. 特点 记得时不时回顾一下背景特点&#xff0c;加深对C语言的理解。

【学习记录】调试千寻服务+DTU+导远RTK过程的记录

最近调试车载定位的时候&#xff0c;遇到了一些问题&#xff0c;千寻服务已经正确配置到RTK里面了&#xff0c;但是导远的定位设备一直显示RTK浮动解&#xff0c;通过千寻服务后台查看状态&#xff0c;长时间显示不合法的GGA值。 首先&#xff0c;通过四处查资料&#xff0c;千…

深入理解JMM

一、什么是JMM JMM&#xff08;java memory model&#xff09;Java内存模型&#xff1a;是java虚拟机规范中定义的一组规范&#xff0c;用于屏蔽掉各种硬件和操作系统的内存访问差异&#xff0c;以实现让JAVA程序在各平台都能达到一致的并发结果。其主要规定了线程和内存之间的…

【优选算法】专题1 -- 双指针 -- 移动零

前言: &#x1f4da;为了提高算法思维&#xff0c;我会时常更新这个优选算法的系列&#xff0c;这个专题是关于双指针的练习 &#x1f3af;个人主页&#xff1a;Dream_Chaser&#xff5e;-CSDN博客 一.移动零&#xff08;easy&#xff09; 描述&#xff1a; 「数组分两块」是⾮…

初识web自动化测试,快速成长指南

自动化 说明 让机器设备代替人为完成指定目标的而过程 优点 减少劳动力提高效率(批量生产)提高产品质量规格统一标准 自动化测试 概念 : 让程序代替人工去验证系统功能的过程 自动化测试能解决什么问题&#xff1f; 解决-回归测试 [重点]解决-压力测试解决-兼容性测试 …

Ubuntu 14.04:安装PaddlePaddle(Conda安装)

目录 一、PaddlePaddle 概要 二、PaddlePaddle安装要求 三、PaddlePaddle安装 3.1 安装 Anaconda3 3.2 创建Anaconda虚拟环境&#xff08;python 3.8&#xff09; 3.3 进入Anaconda虚拟环境 3.4 检测 Anaconda 虚拟环境配置是否符合PaddlePaddle安装要求 3.4.1 确认 py…

掘根宝典之C++类型别名,关键字typedef,auto,decltype

类型别名 在C中&#xff0c;我们可以使用typedef关键字或using关键字来创建类型别名。下面是两种方式的示例&#xff1a; 使用typedef关键字创建类型别名&#xff1a; typedef int myInt; typedef float myFloat;myInt a;//等价int a; myFloat b;//等价float b; 使用using关…

Python面向对象构造函数:手把手教你如何玩转对象初始化

我们都知道&#xff0c;Python是一个面向对象的语言&#xff0c;这意味着我们可以用类来定义对象的属性和方法。而构造函数&#xff0c;就是当我们创建一个新的对象时&#xff0c;会自动调用的特殊方法。那么&#xff0c;如何玩转这个构造函数呢&#xff1f; 首先&#xff0c;…

YoloV8改进策略:下采样改进|HWD改进下采样

摘要 本文使用HWD改进下采样&#xff0c;在YoloV8的测试中实现涨点。 论文解读 在卷积神经网络&#xff08;CNNs&#xff09;中&#xff0c;极大池化或跨行卷积等下采样操作被广泛用于聚合局部特征、扩大感受野和最小化计算开销。然而&#xff0c;对于语义分割任务&#xff…

golang中new和make的区别

1. 先看一个例子 package mainimport "fmt"func main() {var a *int*a 10fmt.Println(*a) }运行结果是啥呢&#xff1f; 问&#xff1a;为什么会报这个panic呢&#xff1f; 答&#xff1a;因为如果是一个引用类型&#xff0c;我们不仅要声明它&#xff0c;还要为…