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

相关推荐
合作小小程序员小小店3 小时前
web网页开发,在线物流管理系统,基于Idea,html,css,jQuery,jsp,java,SSM,mysql
java·前端·后端·spring·intellij-idea·web
这周也會开心4 小时前
SpringMVC整理
java·springmvc
東雪木4 小时前
Spring Boot 2.x 集成 Knife4j (OpenAPI 3) 完整操作指南
java·spring boot·后端·swagger·knife4j·java异常处理
数学难4 小时前
Java面试题2:Java线程池原理
java·开发语言
Charles_go4 小时前
C#8、有哪些访问修饰符
java·前端·c#
qwer12321ck764 小时前
srcType instanceof Class 及泛型 vs 普通类
java
咸鱼求放生4 小时前
Java 8 Stream API
java·开发语言
moiumxf0278q4 小时前
C++中智能指针是如何工作的?
java·jvm·c++
尼古拉斯·纯情暖男·天真·阿玮5 小时前
泛型与数据结构
java·数据结构