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

相关推荐
百锦再5 小时前
React编程高级主题:测试代码
android·前端·javascript·react.js·前端框架·reactjs
JH30736 小时前
SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案
java·spring boot·spring
2501_916008897 小时前
全面介绍Fiddler、Wireshark、HttpWatch、SmartSniff和firebug抓包工具功能与使用
android·ios·小程序·https·uni-app·iphone·webview
Coder_Boy_7 小时前
技术让开发更轻松的底层矛盾
java·大数据·数据库·人工智能·深度学习
玉梅小洋7 小时前
Windows 10 Android 构建配置指南
android·windows
invicinble7 小时前
对tomcat的提供的功能与底层拓扑结构与实现机制的理解
java·tomcat
较真的菜鸟8 小时前
使用ASM和agent监控属性变化
java
黎雁·泠崖8 小时前
【魔法森林冒险】5/14 Allen类(三):任务进度与状态管理
java·开发语言
Libraeking9 小时前
视觉篇:Canvas 自定义绘图与高级动画的华丽圆舞曲
android·经验分享·android jetpack
qq_12498707539 小时前
基于SSM的动物保护系统的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·毕业设计·ssm·计算机毕业设计