ANR分析及解决方案

ANR分析及解决方案

  • 首先,什么是ANR?
  • 那么,为什么会发生ANR?
  • 哪些场景会造成ANR?
  • ANR触发机制
  • 如何避免ANR?
  • 发生ANR异常怎么处理?

首先,什么是ANR?

ANR(Application Not responding):是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间仍未能得到有效响应或者响应时间过长,都会造成ANR。
在 Android 里,应用程序的响应性是由 ActivityManager 和 WindowManager 系统服务监视的。当它监测到以下情况中的一个时,Android 就会针对特定的应用程序显示 ANR。

那么,为什么会发生ANR?

  • 主线程被 IO 操作(从 4.0 之后网络 IO 不允许在主线程中)阻塞;
  • 主线程中存在耗时的计算;
  • 主线程中错误的操作,比如 Thread.wait 或者 Thread.sleep 等等…

哪些场景会造成ANR?

  • Service Timeout:比如前台服务在20s内未执行完成;
  • BroadcastQueue Timeout:比如前台广播在10s内未执行完成;
  • ContentProvider Timeout:内容提供者,在publish过超时10s;
  • InputDispatching Timeout:输入事件分发超时5s,包括按键和触摸事件等等…

ANR触发机制

  • service超时机制:超过一定时间没有执行完相应操作来触发移除延时消息,则会触发anr;
  • BroadcastReceiver超时机制:有序广播的总执行时间超过 2* receiver个数 * timeout时长,则会触发anr;有序广播的某一个receiver执行过程超过 timeout时长,则会触发anr;
  • input超时机制:input的超时机制并非时间到了就会触发anr,而是处理后续上报事件的过程才会去检测是否触发anr;
  • provider超时机制:provider的超时是在provider进程首次启动的时候才会检测,当provider进程已启动的场景,再次请求provider并不会触发provider超时;

如何避免ANR?

  1. 避免在主线程执行耗时操作
    • 使用异步处理:对于网络请求、数据库操作、复杂计算、大文件读写等耗时操作,应该在子线程或使用异步任务(如AsyncTask,尽管官方已不推荐使用,建议使用Thread、HandlerThread、ExecutorService或Kotlin Coroutines等)中执行,避免在主线程中进行耗时操作,从而避免主线程被阻塞;
    • 使用LiveData、Flow(Kotlin)或RxJava这些库在主线程安全地处理异步数据更新;
  2. 优化UI更新和绘制
    • 减少布局层次:简化布局,减少嵌套,提高渲染效率;
    • 使用ViewHolder模式:在列表滚动等场景中,利用ViewHolder减少视图的重复创建;
    • 避免过度绘制:减少视图重叠,使用工具检测并优化;
    • 使用Handler和Looper:在需要进行UI更新的时候,确保在UI线程中进行,可以使用Handler或者Looper来进行UI更新;
  3. 响应系统事件及时
    • BroadcastReceiver、Service:在BroadcastReceiver的onReceive()方法或Service的回调中尽快完成操作,或者启动新线程处理耗时操作;
    • ContentProvider:查询数据时尽量快速返回,复杂查询应异步处理;
  4. 监控和处理后台任务
    • 使用JobScheduler或WorkManager:安排后台任务,特别是那些需要网络连接的任务,以避免在不适合执行时阻塞UI线程;
    • 超时处理:对于所有异步操作,设定合理的超时机制,避免无限等待;
  5. 优化数据库查询
    • 索引优化:对频繁查询的字段建立索引,加快查询速度;
    • 分批查询:避免一次性查询大量数据,考虑分批次加载;
    • 异步查询:在进行大量的数据库操作时,尽量避免在主线程中直接进行,可以考虑使用异步机制或者数据库事务来优化数据库操作
  6. 处理主线程阻塞
    • 使用StrictMode进行性能监测:Android提供了StrictMode来检测应用的性能问题,可以通过StrictMode来发现一些可能引起ANR的问题;
    • 监控主线程:使用Choreographer或第三方工具监控主线程的执行情况,及时发现阻塞源;
    • 合理使用轮询和超时机制:在进行一些IO操作时要避免直接使用阻塞式方法,可以使用轮询或者设置超时时间来避免线程被阻塞;
  7. 适配硬件差异
    • 考虑设备性能:针对低端设备优化应用,减少资源消耗,提高流畅度;
  8. 用户交互反馈
    • 显示进度条或加载提示:在执行耗时操作时,给用户明确的视觉反馈,让用户知道应用正在工作而不是卡死。

总结:将所有耗时操作,比如访问网络,Socket 通信,查询大量 SQL 语句,复杂逻辑计算等都放在子线程中去,然后通过 handler.sendMessage、runonUIThread、 AsyncTask、RxJava 等方式更新 UI。无论如何都要确保用户界面的流畅度。如果耗时操作需要让用户等待,那么可以在界面上显示进度条。

发生ANR异常怎么处理?

  1. 收集ANR日志
    • 查看设备日志:连接设备到电脑,使用adb logcat命令收集日志,重点关注带有ANR关键字的信息,它会包含ANR发生的时间、涉及的线程、堆栈跟踪等详细信息;
    • 应用专有日志:如果应用内实现了Crash上报机制,检查是否有相关的ANR报告或日志记录;
  2. 分析ANR日志
    • 识别阻塞线程:日志中会指出哪个线程发生了阻塞(通常是主线程),并提供该线程的堆栈跟踪;
    • 分析堆栈跟踪:通过堆栈跟踪,确定导致阻塞的具体操作或函数调用。重点关注主线程中执行的耗时操作;
  3. 定位问题代码
    • 根据堆栈信息,回到代码中定位到问题所在的具体位置;
    • 检查该位置是否有网络请求、数据库操作、大量数据处理、UI布局复杂度过高、锁的竞争等问题;
  4. 优化代码
    • 异步处理:将耗时操作移至子线程或使用异步任务执行;
    • 优化操作:优化数据库查询、减少布局复杂度、使用轻量级数据结构等;
    • 合理使用缓存:预加载或缓存数据,减少实时计算和加载时间;
    • 数据库操作的优化:索引优化、分批查询、异步查询;
    • 优化IO操作:在进行一些IO操作时,避免使用阻塞式方法,可以考虑使用轮询或者设置超时时间来避免线程被阻塞;
  5. 增加超时和错误处理
    • 为网络请求、数据库操作等添加超时处理,防止无限等待;
    • 实现重试机制和错误回调,提高应用的健壮性;
  6. 测试与监控
    • 单元测试和压力测试:编写测试用例,模拟高负载情况,确保优化有效;
    • 持续监控:集成ANR监控工具或服务,如Firebase Performance Monitoring,及时发现并解决新出现的ANR问题;
  7. 用户反馈
    • 如果ANR发生在用户设备上,考虑提供一种机制让用户可以轻松反馈问题详情,这有助于快速定位问题;
  8. 避免未来ANR
    • 遵循最佳实践:持续学习和应用Android开发的最佳实践,特别是关于线程管理和资源优化的指南;
    • 代码审查:团队内部实施严格的代码审查流程,确保代码质量,避免引入可能导致ANR的代码;
    • 使用StrictMode进行性能监测:Android提供了StrictMode来检测应用的性能问题,可以通过StrictMode来发现潜在的引起ANR的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/50833.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

27、美国国家冰雪中心(NSIDC)海冰密集度月数据下载与处理

文章目录 一、前言二、数据下载三、使用Ponply查看数据结构四、代码一、前言 处理美国国家冰雪中心(NSIDC)的海冰密集度月度数据时,坐标转换是一个重要的步骤。NSIDC提供的数据通常采用极地球面坐标系,需要将其转换为常用的地理坐标系(如经纬度)以便进行分析和可视化。 坐…

python debug怎么用

1.打开pycharm,新建一个python程序,命名为excel.py。 2.直接贴出代码,如果是hello world就不存调试的问题了! 3.介绍调试的菜单操作,在【菜单栏】选择【RUN】,下拉菜单里选择【debug excel.py】或者【Debug…

【C++】类与对象--初始化列表,类型转换,static,友元

文章目录 前言一、初始化列表1.1 初始化列表概述1.2 初始化列表注意事项初始化列表代码示例 二、类类型转换2.1 类类型转换2.2 代码示例 三.static成员3.1 静态成员变量3.2 代码示例 四.友元4.1友元概述4.2 友元特点4.3 友元代码示例 五.内部类5.1 内部类特点5.2 代码示例 六.匿…

掀桌子了!原来是咱们的大屏设计太酷,吓着前端开发老铁了

掀桌子了!原来是咱们的大屏设计太酷,吓着前端开发老铁了 艾斯视觉观点认为:在软件开发的世界里,有时候创意和设计的火花会擦得特别亮,以至于让技术实现的伙伴们感到既兴奋又紧张。这不,我们的设计团队刚刚…

利用AI能力实现一个生成掘金、CSDN文章的总结并生成思维脑图

背景 为了快速了解文章重点!! 设计思路 1、根据文章链接、获取文章内容 2、编写 prompt 3、利用 markmap 显示思维导图 实现 获取文章内容 利用爬虫技术,简单利用 axios 获取链接内容,然后通过 cheerio 获取相关元素。 编码…

靶机Metasploitable2的安装

Metasploitable2是一款基于Ubuntu Linux的操作系统。Metasploitable2是一个虚拟机文件,从网上下载解压之后就可以直接使用,无需安装。该系统本身设计作为安全工具测试和演示常见漏洞攻击的靶机,所以它存在大量未打补丁漏洞,并且开…

C语言中的IO控制流

文章目录 一、什么是C语言中的IO控制流二、open函数 1.使用open函数创建文件2.使用使用open函数打开文件三、文件的权限四、文件的描述符五、read函数六、write函数七、lseek函数八、close函数 一、什么是C语言中的IO控制流 在linux系统中一切皆文件,C语言中的IO控…

13.2 MongoDB

13.2 MongoDB 1. 概述2. docker安装3. SpringBoot整合MongoDB3.1 依赖3.2 配置连接1. 基于`yml`配置2. 基于配置类配置3.3 启动项坑1坑23.4 新增业务1. 实体类映射2. 数据层3. 业务层4. 控制层5. 测试结果3.5 单条记录查询业务1. 数据层2. 业务层3. 控制层4. 断点测试3.6 分页查…

【Rust光年纪】极致性能与灵活选择:Rust语言数学优化库详解

Rust语言中的数学优化:六大利器汇总 前言 在当今信息时代,数据处理和数学优化成为了各行各业中不可或缺的重要环节。为了满足对高效、快速计算的需求,Rust语言逐渐成为了许多开发者的首选,因其性能优越、并发安全等特点。本文将…

【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针

目录 常量指针和指向常量的指针有什么区别?1. 指向常量的指针(Pointer to Constant)声明方式:示例:解释: 2. 常量指针(Constant Pointer)声明方式:示例:解释&…

zookeeper子结点方式实现分布式锁(阻塞,非阻塞)

一,阻塞式和非阻塞式 “阻塞”和“非阻塞”只是一个人为的概念,“阻塞”说的是一个线程去尝试获取锁,如果失败,就阻塞在这里,监听到持有锁的线程释放,再次去尝试获取。 而“非阻塞”是我尝试一次失败了&am…

泛域名绑定到wordpress网站二级目录

要将WordPress的泛域名绑定到二级目录&#xff0c;你需要在你的服务器上修改Apache或Nginx配置文件。以下是两种最常见的服务器配置的示例&#xff1a; Apache服务器 编辑你的虚拟主机配置文件&#xff0c;通常位于/etc/apache2/sites-available/目录下。 <VirtualHost *…

2024 暑假友谊赛-热身1

[ABC102D] Equal Cut - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路:找在区间[2,n-1]中找到i,j,k三个点,把序列分割成4个区间:[1,i],[i1,j],[j1,k],[k1,n] 暴力的做法是枚举i,j,k加上前缀和是o(n^3)的 key:"考虑枚举处于中间的j&#xff0c;然后用i平衡左两个区间,…

【踩坑系列-JS】iframe中的url参数获取

Author&#xff1a;赵志乾 Date&#xff1a;2024-07-24 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 1. 问题描述 系统A的页面中以iframe的方式嵌入了系统B的页面&#xff0c;并需要将A页面url中的参数传递给B页面。 最初的实现方式是&am…

【es】elasticsearch 自定义排序-按关键字位置排序

一 背景 要求es查询的结果按关键字位置排序&#xff0c;位置越靠前优先级越高。 es版本7.14.0&#xff0c;项目是thrift&#xff0c;也可以平替springboot&#xff0c;使用easyes连接es。 二 easyes使用 配easyes按官方文档就差不多了 排序 | Easy-Es 主要的一个问题是easy…

Lua实现面向对象以及类的继承

0.简单前言 1、面向对象主要四个特征&#xff1a;封装&#xff0c;继承&#xff0c;多态&#xff0c;抽象 2、Lua是种简单精致小巧的语言&#xff0c;其本质是个表&#xff08;table&#xff09;&#xff0c;变量和方法皆可看作为该表的元素。 P.S. 该博客和代码为个人编写习…

Golang零基础入门课_20240726 课程笔记

视频课程 最近发现越来越多的公司在用Golang了&#xff0c;所以精心整理了一套视频教程给大家&#xff0c;这个只是其中的第一部&#xff0c;后续还会有很多。 视频已经录制完成&#xff0c;完整目录截图如下&#xff1a; 课程目录 01 第一个Go程序.mp402 定义变量.mp403 …

【工具类】Java DES加密解密

package com.util;import java.security.Key; import java.security.SecureRandom;import javax.crypto.Cipher; import javax.crypto.KeyGenerator;import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; /*** DES算法*/ SuppressWarnings("restriction")…

Leetcode—263. 丑数【简单】

2024每日刷题&#xff08;147&#xff09; Leetcode—263. 丑数 实现代码 class Solution { public:bool isUgly(int n) {if(n < 0) {return false;}for(const int prime: {2, 3, 5}) {while(n % prime 0) {n / prime;}}return n 1;} };运行结果 之后我会持续更新&#…

ORACLE RAC 环境真的不能开启主机防火墙吗?

一直以来&#xff0c;安装ORACLE RAC&#xff0c;都是直接关闭防火墙&#xff0c;要问为什么&#xff0c;说是官方的推荐&#xff0c;具体可以见 RAC instabilities due to firewall (netfilter/iptables) enabled on the cluster interconnect (Doc ID 554781.1)&#xff0c;启…