Android:在项目当中可能会遇到的ANR,应该如何解决?

一、可能遇到的问题

1.1、主线程加载大图

问题: 加载高分辨率图片,比如当你在 XML 布局文件中直接设置 android:background属性引用高分辨率图片时,系统会在主线程加载和解码这张图片​​。

解决方法:使用 Glide 异步加载图片

scss 复制代码
Glide.with(context)
     .load(imageUrl)
     .diskCacheStrategy(DiskCacheStrategy.ALL)
     .into(imageView);

1.2、主线程读取配置文件

问题:解析大型 JSON/XML 配置文件,比如有时候,我们会将一些网络的配置数据放到文件里面,那么读取配置文件就会占用主线程

解决方法:使用协程异步读取

scss 复制代码
lifecycleScope.launch(Dispatchers.IO) {
    val config = assets.open("config.json").bufferedReader().use { it.readText() }
    val parsedConfig = Json.decodeFromString<Config>(config)
    
    withContext(Dispatchers.Main) {
        applyConfig(parsedConfig)
    }
}

1.3、主线程读取SP

同上,我们读取数据的时候,也要使用协程来代替。

1.4、字体加载

同上,我们读取数据的时候,也要使用协程来代替。 ResourcesCompat.getFont阻塞主线程,当通过 ResourcesCompat.getFont()或 XML 属性加载时,会在主线程执行。

问题代码

ini 复制代码
val typeface = ResourcesCompat.getFont(context, R.font.roboto_medium)

或

val typeface = Typeface.createFromAsset(
    context.assets, 
    "fonts/roboto_medium.ttf"
)
textView.typeface = typeface

使用协程实现异步加载

scss 复制代码
// 异步加载字体
val typeface by lazy {
    runBlocking(Dispatchers.IO) {
        ResourcesCompat.getFont(context, R.font.large_font)
    }
}

还有一些网络操作,或者数据库也有可能导致耗时,不过现在越来越先进了,这两个不加协程,都会编译错误提示你。

二、使用工具帮助检测哪里可能存在耗时的地方

使用StrictMode,在Application的oncreate里面配置

less 复制代码
// 线程策略
StrictMode.setThreadPolicy(
    StrictMode.ThreadPolicy.Builder()
        .detectDiskReads()        // 检测磁盘读取
        .detectDiskWrites()       // 检测磁盘写入
        .detectNetwork()          // 检测网络操作
        .detectCustomSlowCalls()  // 检测自定义耗时调用
        .penaltyLog()            // 违规时打印日志
        //.penaltyDeath()
        .build()
)

// VM策略
StrictMode.setVmPolicy(
    StrictMode.VmPolicy.Builder()
        .detectLeakedSqlLiteObjects()     // 检测 SQLite 对象泄漏
        .detectLeakedClosableObjects()    // 检测未关闭的 Closable 对象泄漏
        .detectActivityLeaks()            // 检测 Activity 泄漏
        .penaltyLog()                     // 违规时打印日志
        //.penaltyDeath()
        .build()
)

然后在控制台搜索StrictMode即可找到可能存在耗时的地方。

注意:我们现在的手机内存是越来越大了,但你的手机不代表别人的手机,根据监控报错,还是有很多人的手机配置比较低,所以我们要把这些当回事。

可以看到,上述的情况,大部分都是通过异步加载来解决问题的。但有些情况是异步解决不了的。

  1. 死锁,锁竞争
  2. 视图布局过于复杂​:测量(onMeasure)、布局(onLayout)、绘制(onDraw)过程耗时过长。

这些就需要,优化代码逻辑才能解决。

因此,解决ANR需要结合​​异步化​ ​、​​代码优化​ ​和​​性能监测​​等一系列手段。

相关推荐
香蕉大香蕉(06敬畏市场)4 分钟前
MySQL 单点详解(01)
java·数据库·mysql·面试·博客·实习
LaughingZhu20 分钟前
Product Hunt 热榜 2026-10-30:Empacer、Scape、Floot in ChatGPT
java·前端·数据库·人工智能·chatgpt·notion
niucloud-admin38 分钟前
NIUCLOUD PHP SAAS上门家政使用文档:服务保障
java·开发语言·php
booboosui1 小时前
删掉一个住在本机的 agent:8 处要清,顺序不能反
android
IT枫斗者枫哥1 小时前
CompletableFuture失败后返回空列表:异常没了,业务含义也变了
java·后端
知识搬运临时工1 小时前
一个模板把 AEM 拖进 Full GC 死亡螺旋:300% CPU、7 GB 堆、310 万行堆栈
java·aws
用户432935928051 小时前
CoAP还是MQTT:1万只Cat.1水表三个月带宽续航实测
java
知守观1 小时前
多模块架构演进:横向分层 vs 纵向领域,13 个真实项目的切分对照
java·后端·微服务
hcgeng1 小时前
Android获取崩溃日志
android