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需要结合​​异步化​ ​、​​代码优化​ ​和​​性能监测​​等一系列手段。

相关推荐
Filotimo_3 分钟前
在java开发中:JSON序列化和JSON反序列化
java·microsoft·json
光芒Shine5 分钟前
【Android-开发指南】
android
czlczl200209256 分钟前
SpringBoot实践:从验证码到业务接口的完整交互生命周期
java·spring boot·redis·后端·mysql·spring
Han_coding12087 分钟前
从原理到实战:基于游标分页解决深分页问题(附源码方案)
java·服务器·数据库·spring boot·spring cloud·oracle
二等饼干~za8986688 分钟前
碰一碰发视频系统源码开发搭建--技术分享
java·运维·服务器·重构·django·php·音视频
ss27311 分钟前
线程池优雅关闭:线程池生命周期管理:四种关闭策略的实战对比
java·jvm·算法
哈龙_9912 分钟前
Android 文件下载库ketch示例
android
不能只会打代码14 分钟前
蓝桥杯--生命之树(Java)
java·算法·蓝桥杯·动态规划·贪心
多则惑少则明16 分钟前
AI大模型实用(九)Java快速实现智能体整理(使用LangChain4j-agentic + Tool)
java·人工智能·springai·langchain4j