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

相关推荐
行业研究员9 分钟前
Android内置GPS与腾讯地图定位技术对比分析
android·android定位·腾讯地图定位
0x5311 分钟前
Java网络编程(四)
java·网络
ly768922 分钟前
Java 设计模式详解:从原则到 23 种经典模式
java·开发语言·设计模式
萧瑟余晖39 分钟前
Java深入解析篇三十之Java日志框架
java·开发语言
Android-Flutter1 小时前
android WMS 详解(二)
android·kotlin
Suxing91 小时前
C语言基础分享:从“租房”到“拆迁”,C语言动态内存管理
java·数据结构·算法
减瓦1 小时前
别让 Java 版本选择变成生产事故
java
ikun_文1 小时前
Java集合框架Collection拓展进阶
java·java ee
游戏开发爱好者81 小时前
App Store 上传 IPA 自动化,.p8 密钥认证与 CI/CD 接入实战
android·运维·ci/cd·小程序·uni-app·自动化·iphone
码匠许师傅2 小时前
【C++ 面试真题】聊聊 C++ 的虚函数和多态
java·c++·面试