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

2024-03-15 16:20

本文主要是介绍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:协程基础

这篇关于Kotlin:runBlocking导致App应用出现ANR问题实例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/812544

相关文章

java String.join()方法实例详解

《javaString.join()方法实例详解》String.join()是Java提供的一个实用方法,用于将多个字符串按照指定的分隔符连接成一个字符串,这一方法是Java8中引入的,极大地简化了... 目录bVARxMJava String.join() 方法详解1. 方法定义2. 基本用法2.1 拼接

如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socket read timed out的问题

《如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socketreadtimedout的问题》:本文主要介绍解决Druid线程... 目录异常信息触发场景找到版本发布更新的说明从版本更新信息可以看到该默认逻辑已经去除总结异常信息触发场景复

Python使用Tkinter打造一个完整的桌面应用

《Python使用Tkinter打造一个完整的桌面应用》在Python生态中,Tkinter就像一把瑞士军刀,它没有花哨的特效,却能快速搭建出实用的图形界面,作为Python自带的标准库,无需安装即可... 目录一、界面搭建:像搭积木一样组合控件二、菜单系统:给应用装上“控制中枢”三、事件驱动:让界面“活”

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

VS配置好Qt环境之后但无法打开ui界面的问题解决

《VS配置好Qt环境之后但无法打开ui界面的问题解决》本文主要介绍了VS配置好Qt环境之后但无法打开ui界面的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目UKeLvb录找到Qt安装目录中designer.UKeLvBexe的路径找到vs中的解决方案资源

如何确定哪些软件是Mac系统自带的? Mac系统内置应用查看技巧

《如何确定哪些软件是Mac系统自带的?Mac系统内置应用查看技巧》如何确定哪些软件是Mac系统自带的?mac系统中有很多自带的应用,想要看看哪些是系统自带,该怎么查看呢?下面我们就来看看Mac系统内... 在MAC电脑上,可以使用以下方法来确定哪些软件是系统自带的:1.应用程序文件夹打开应用程序文件夹

MySQL启动报错:InnoDB表空间丢失问题及解决方法

《MySQL启动报错:InnoDB表空间丢失问题及解决方法》在启动MySQL时,遇到了InnoDB:Tablespace5975wasnotfound,该错误表明MySQL在启动过程中无法找到指定的s... 目录mysql 启动报错:InnoDB 表空间丢失问题及解决方法错误分析解决方案1. 启用 inno

Java使用MethodHandle来替代反射,提高性能问题

《Java使用MethodHandle来替代反射,提高性能问题》:本文主要介绍Java使用MethodHandle来替代反射,提高性能问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录一、认识MethodHandle1、简介2、使用方式3、与反射的区别二、示例1、基本使用2、(重要)

Linux lvm实例之如何创建一个专用于MySQL数据存储的LVM卷组

《Linuxlvm实例之如何创建一个专用于MySQL数据存储的LVM卷组》:本文主要介绍使用Linux创建一个专用于MySQL数据存储的LVM卷组的实例,具有很好的参考价值,希望对大家有所帮助,... 目录在Centos 7上创建卷China编程组并配置mysql数据目录1. 检查现有磁盘2. 创建物理卷3. 创

电脑蓝牙连不上怎么办? 5 招教你轻松修复Mac蓝牙连接问题的技巧

《电脑蓝牙连不上怎么办?5招教你轻松修复Mac蓝牙连接问题的技巧》蓝牙连接问题是一些Mac用户经常遇到的常见问题之一,在本文章中,我们将提供一些有用的提示和技巧,帮助您解决可能出现的蓝牙连接问... 蓝牙作为一种流行的无线技术,已经成为我们连接各种设备的重要工具。在 MAC 上,你可以根据自己的需求,轻松地