android ANR

本文介绍了Android平台上的ANR(Application Not Responding)现象,包括其定义、类型、产生原因及如何避免ANR的发生。文中还提供了诊断ANR的步骤及命令行工具。

一:什么是ANR

ANR:Application Not Responding,即应用无响应 

    ANR定义:在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application Not Responding)对话框。用户可以选择“等待”而让程序继续运行,也可以选择“强制关闭”。所以一个流畅的合理的应用程序中不能出现anr,而让用户每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要,这样系统不会显示ANR给用户。

    默认情况下,在android中Activity的最长执行时间是5秒,BroadcastReceiver的最长执行时间则是10秒。

二:ANR的类型

ANR一般有三种类型:

1KeyDispatchTimeout(5 seconds) --主要类型  按键或触摸事件在特定时间内无响应

2BroadcastTimeout(10 seconds)   BroadcastReceiver在特定时间内无法处理完成

3ServiceTimeout(20 seconds) --小概率类型    Service在特定的时间内无法处理完成

三:KeyDispatchTimeout

Akey or touch event was not dispatched within the specified time(按键或触摸事件在特定时间内无响应)

在Android里,应用程序的响应性是由Activity Manager和WindowManager系统服务监视的 。当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR:

1.在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸)
2.BroadcastReceiver在10秒内没有执行完毕

造成以上两点的原因有很多,比如在主线程中做了非常耗时的操作,比如说是下载,io异常等。

  潜在的耗时操作,例如网络或数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者以数据库操作为例,通过异步请求的方式)来完成。然而,不是说你的主线程阻塞在那里等待子线程的完成——也不是调用 Thread.wait()或是Thread.sleep()。

替代的方法是,主线程应该为子线程提供一个Handler,以便完成时能够提交给主线程。以这种方式设计你的应用程序,将能保证你的主线程保持对输入的响应性并能避免由于5秒输入事件的超时引发的ANR对话框。

四:为什么会超时呢?

   超时时间的计数一般是从按键分发给app开始。超时的原因一般有两种

  (1)当前的事件没有机会得到处理(即UI线程正在处理前一个事件,没有及时的完成或者looper被某种原因阻塞住了)

  (2)当前的事件正在处理,但没有及时完成。

五:如何避免KeyDispatchTimeout

    1、运行在主线程里(UI线程尽量只做跟UI相关的工作)的任何方法都尽可能少做事情。特别是,Activity应该在它的关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建操作。(可以采用重新开启子线程的方式,然后使用Handler+Message的方式做一些操作,比如更新主线程中的ui等)

   2、应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。但不再是在子线程里做这些任务(因为 BroadcastReceiver的生命周期短),替代的是,如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个 Service。(此处需要注意的是可以在广播接受者中启动Service,但是却不可以在Service中启动broadcasereciver

   3、避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现。

   4、尽量用Handler来处理UIthread和别的thread之间的交互

   5耗时的工作(比如数据库操作,I/O,连接网络或者别的有可能阻碍UI线程的操作)把它放入单独的线程处理

六:UI线程

说了那么多的UI线程,那么哪些属于UI线程呢?

UI线程主要包括如下:

  1. Activity:onCreate(), onResume(), onDestroy(), onKeyDown(), onClick(),etc

  2. AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel,etc

  3. Mainthread handler: handleMessage(), post*(runnable r), etc

  4. other

:如何去分析ANR

如何获取呢?可以用如下命令获取

  1. $chmod 777 /data/anr

  2. $rm /data/anr/traces.txt

  3. $ps

  4. $kill -3PID

  5. adbpull data/anr/traces.txt ./mytraces.txt

八:如何调查并解决ANR

1:首先分析log

2: trace.txt文件查看调用stack.

3: 看代码

4:仔细查看ANR的成因(iowait?block?memoryleak?


 小小的总结一下吧:anr异常也是在程序中自己经常遇到的问题,主要的解决办法自己最常用的就是不要在主线程中做耗时的操作,而应放在子线程中来实现,比如采用Handler+mesage的方式,或者是有时候需要做一些和网络相互交互的耗时操作就采用asyntask异步任务的方式(它的底层其实Handler+mesage有所区别的是它是线程池)等,在主线程中更新UI。

### 分析和解决 Android 应用中的 ANR(Application Not Responding)问题 Android 中的 ANR(Application Not Responding)是指应用程序在一定时间内没有响应用户的输入事件或未能及时完成特定组件的操作,系统会判定为应用无响应,并弹出 ANR 对话框。分析和解决 ANR 问题对于提升应用的稳定性与用户体验至关重要。 #### ANR 的类型与触发机制 ANR 主要有以下几种类型,每种类型的触发时间阈值不同: - **Input Event Timeout(输入事件超时)**:主线程在 5 秒内未响应输入事件,例如点击、滑动等。 - **Broadcast Timeout(广播超时)**:前台广播在 15 秒内未完成,后台广播在 60 秒内未完成。 - **Service Timeout(服务超时)**:前台服务在 20 秒内未完成,后台服务在 200 秒内未完成。 - **ContentProvider Timeout(内容提供者超时)**:在 10 秒内未发布内容提供者。 这些机制确保了系统资源的合理调度和用户体验的流畅性。 #### ANR 日志的获取方法 为了分析 ANR 问题,首先需要获取相关的日志信息: - **实时日志捕获**:使用 `adb logcat -v time | grep "ANR in\|am_anr"` 过滤 ANR 关键词。 - **导出 traces 文件**:通过 `adb pull /data/anr/traces.txt` 获取线程堆栈信息(每次新的 ANR 会覆盖旧文件)。 - **完整系统报告**:使用 `adb bugreport` 获取包含 CPU、内存、I/O 等系统数据的完整报告。 这些日志提供了关于 ANR 发生时的应用状态、线程状态和系统资源使用情况。 #### ANR 的核心分析流程 分析 ANR 日志的流程主要包括以下几个步骤: 1. **确认 ANR 类型**:根据日志中的关键词确定 ANR 的具体类型。 2. **分析 trace 文件**:查看线程堆栈信息,识别主线程是否被阻塞、是否存在锁竞争或 Binder 线程耗尽等问题。 3. **定位根因**:通过分析 trace 文件中的调用栈和线程状态,确定 ANR 的根本原因。 #### ANR 治理方案 治理 ANR 问题需要从多个方面入手: - **透彻理解机制**:掌握 Input、Service、Broadcast 和 Binder 等超时机制,以及系统调度原理。 - **强大的监控体系**:线上平台需要抓取 ANR 事件、主线程堆栈和系统 Traces 文件;线下使用 Systrace、Perfetto、Profiler 和 `adb bugreport` 工具进行分析。 - **精准根因分析**:区分主线程阻塞、Binder 线程耗尽、系统资源瓶颈等问题,利用 Traces 文件分析锁和线程状态是关键突破口。 - **针对性优化**: - **主线程优化**:避免在主线程上执行耗时操作,优化布局和视图层次。 - **Binder 调用优化**:异步化 Binder 调用,优化服务端性能。 - **系统资源优化**:关注 CPU、内存和 I/O 使用情况,避免资源瓶颈。 - **现代化架构**:采用 WorkManager、协程/RxJava、响应式架构和生命周期感知组件,提高应用的响应能力。 - **闭环流程与文化**:设定目标、监控告警、深度分析、有效修复、严格验证、灰度发布、持续复盘和知识沉淀。将稳定性(特别是 ANR 率)作为核心质量指标。 #### 使用工具分析 ANR 问题 - **Android Profiler**:通过 Android Studio 的 Profiler 工具可以实时监控 CPU、内存和网络使用情况,帮助识别 ANR 的潜在原因。 - **StrictMode**:在开发阶段启用 StrictMode 可以检测主线程上的违规操作,如网络请求或数据库操作,从而提前发现可能导致 ANR 的问题。 #### 示例代码:使用 StrictMode 检测主线程违规操作 ```java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads() .penaltyLog() .build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectLeakedSqlLiteObjects() .penaltyLog() .build()); } } ``` 通过上述代码,可以在开发阶段检测主线程上的磁盘读取操作,并记录日志以便优化。 --- #### 相关问题 1. 如何通过 Systrace 工具分析 ANR 问题? 2. Android 中如何优化主线程的性能以避免 ANR? 3. 如何在生产环境中监控和捕获 ANR 事件? 4. Android 中如何处理 Binder 线程耗尽导致的 ANR 问题? 5. 如何通过响应式架构减少 ANR 的发生?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值