ANR 发生及处理

本文详细解析了Android应用中ANR(Application Not Responding)现象的原因及应对策略,介绍了触发ANR的具体条件,如主线程执行耗时操作或受到其他进程干扰,并提供了避免ANR的有效方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ANR的全称是application not responding,意思就是程序未响应,类似于我们在windows上见到的程序未响应。ANR发生会使用户觉得我们的程序不友好,那么什么情况会导致ANR的发生呢?

首先ANR的发生是有条件限制的,分为以下三点:

1.只有主线程才会产生ANR,主线程就是UI线程;

2.必须发生某些输入事件或特定操作,比如按键或触屏等输入事件,在BroadcastReceiver或Service的各个生命周期调用函数;

3.上述事件响应超时,不同的context规定的上限时间不同

a.主线程对输入事件5秒内没有处理完毕

b.主线程在执行BroadcastReceiver的onReceive()函数时10秒内没有处理完毕

c.主线程在Service的各个生命周期函数时20秒内没有处理完毕。

那么导致ANR的根本原因是什么呢?简单的总结有以下两点:

1.主线程执行了耗时操作,比如数据库操作或网络编程

2.其他进程(就是其他程序)占用CPU导致本进程得不到CPU时间片,比如其他进程的频繁读写操作可能会导致这个问题。

细分的话,导致ANR的原因有如下几点:

1.耗时的网络访问

2.大量的数据读写

3.数据库操作

4.硬件操作(比如camera)

5.调用thread的join()方法、sleep()方法、wait()方法或者等待线程锁的时候

6.service binder的数量达到上限

7.system server中发生WatchDog ANR

8.service忙导致超时无响应

9.其他线程持有锁,导致主线程等待超时

10.其它线程终止或崩溃导致主线程一直等待

那么如何避免ANR的发生呢或者说ANR的解决办法是什么呢?

1.避免在主线程执行耗时操作,所有耗时操作应新开一个子线程完成,然后再在主线程更新UI。

2.BroadcastReceiver要执行耗时操作时应启动一个service,将耗时操作交给service来完成。

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

                        (二)

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

在Android里,应用程序的响应性是由Activity Manager和WindowManager系统服务监视的 。当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR:
1.在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸)
2.BroadcastReceiver在10秒内没有执行完毕
造成以上两点的原因有很多,比如在主线程中做了非常耗时的操作,比如说是下载,io异常等。


潜在的耗时操作,例如网络或数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者以数据库操作为例,通过异步请求的方式)来完成。然而,不是说你的主线程阻塞在那里等待子线程的完成——也不是调用 Thread.wait()或是Thread.sleep()。替代的方法是,主线程应该为子线程提供一个Handler,以便完成时能够提交给主线程。以这种方式设计你的应用程序,将能保证你的主线程保持对输入的响应性并能避免由于5秒输入事件的超时引发的ANR对话框。
第二:如何避免ANR?
1、运行在主线程里的任何方法都尽可能少做事情。特别是,Activity应该在它的关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建操作。(可以采用重新开启子线程的方式,然后使用Handler+Message的方式做一些操作,比如更新主线程中的ui等)

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

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

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

参考:

http://www.cnblogs.com/mobile-veterans/archive/2012/07/20/2600715.html
http://blog.sina.com.cn/s/blog_618199e60101kvbl.html
http://wenku.baidu.com/link?url=kwhbIuXYJsE6Pw5rBLNQA2U9wSduSMYQBIF5-Oidds2X0FLJs2w_EX-iPvBQ4oXVjhGqYq5xbS1n6QModiw_7KHAoEFyDlAil_eKV3_bUaa

### ANR 原理 ANR(Application Not Responding)是指当 Android 应用程序由于某些原因无法及时响应用户的交互或系统请求时,系统弹出的一个对话框提示用户当前应用无响应。这种现象通常是由于主线程被长时间占用而引起的。 在 Android 中,ANR 主要有以下几种触发条件: 1. **Input Dispatching Timeout (输入事件分发超时)**:如果主线程超过 5 秒未处理任何用户输入事件(如点击、滑动等),则会触发 ANR[^3]。 2. **BroadcastReceiver 超时**:如果 `BroadcastReceiver` 的回调函数 `onReceive()` 执行时间超过了 10 秒,则会触发 ANR[^4]。 3. **Service 启动超时**:如果某个 Service 在启动过程中花费了过长时间(默认为 20 秒),也会导致 ANR 发生。 这些超时行为的根本原因是主线程被阻塞或者过度负载,从而无法及时完成必要的任务。 --- ### ANR 处理流程 #### 1. 确定问题根源 为了有效解决 ANR 问题,首先需要明确引发该问题的具体原因。这可以通过分析日志文件来实现。常见的做法是从 `/data/anr/traces.txt` 文件中提取堆栈跟踪信息并定位到具体的代码位置。 #### 2. 使用异步线程优化性能 为了避免主线程因执行耗时操作而导致卡顿,可以采用多线程技术将繁重的工作转移到后台线程中运行。例如,通过创建子线程或利用现有的并发工具库(如 `AsyncTask`, `HandlerThread`, 或者更现代的 `Kotlin Coroutines` 和 `Java Executor Frameworks` 来管理复杂的计算任务[^5]。 以下是基于 Java 的简单示例展示如何使用 Handler 将工作移至背景线程: ```java new Thread(new Runnable() { @Override public void run() { // 这里放置耗时的操作 performLongRunningOperation(); // 更新UI需切换回主线程 new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { updateUiAfterCompletion(); } }); } }).start(); ``` 对于广播接收器中的情况,推荐的做法是不直接在此处做大量数据处理而是交由 IntentService 完成进一步的任务调度。 #### 3. 减少不必要的资源消耗 除了合理分配线程外,还应关注减少内存泄漏和频繁GC带来的影响。比如关闭不再使用的连接池实例;释放Bitmap对象所占空间等等措施均有助于提升整体流畅度[^1]。 #### 4. 测试与监控 最后,在开发周期内持续进行压力测试以验证改进效果,并借助第三方平台实施线上实时监测以便快速发现潜在隐患[^2]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值