Android ANR

摘要:ANR(Application Not Responding):应用程序没有响应,是Android应用开发及使用中相对比较常见的一种情况,在笔试和面试中也经常会碰到,借此对这个问题进行整理分享。

定义

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

类型

  1. KeyDispatchTimeout(5 seconds) –主要类型按键或触摸事件在特定时间内无响应
  2. BroadcastTimeout(10 seconds) –BroadcastReceiver在特定时间内无法处理完成
  3. ServiceTimeout(20 seconds) –小概率类型 Service在特定的时间内无法处理完成

原因

超时时间的计数一般是从按键分发给app开始。超时的原因一般有两种:
(1)当前的事件没有机会得到处理(即UI线程正在处理前一个事件,没有及时的完成或者looper被某种原因阻塞住了)
(2)当前的事件正在处理,但没有及时完成

分析

  1. 首先分析log
  2. 从trace.txt文件查看调用stack.
  3. 看代码
  4. 仔细查看ANR的成因

查看trace.txt文件

$chmod 777 /data/anr
$rm /data/anr/traces.txt
$ps
$kill -3 PID
//adbpull data/anr/traces.txt ./mytraces.txt 

解决

  1. 减少在UI主线程中设计耗时的操作,例如数据库操作,网络连接操作(android2.3以后已经禁止在UI主线程中进行网络操作)
  2. 通过异步编程,通知UI主线程,避免对UI主线程进行阻塞
  3. 耗时的工作(比如数据库操作,I/O,连接网络或者别的有可能阻碍UI线程的操作)把它放入单独的线程处理
  4. 尽量用Handler来处理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

具体实例参考

http://www.cnblogs.com/purediy/p/3225060.html
http://blog.youkuaiyun.com/leilu2008/article/details/6689405
http://www.cnblogs.com/wanqieddy/archive/2012/05/04/2482661.html

### ANR 的原因 在 Android 应用程序中,ANR 错误通常发生在主线程被阻塞的情况下。如果某个线程占用单一线程时间过长(超过 5 秒),这会阻止用户交互并触发系统的 ANR 警告[^1]。 具体来说,当应用程序未能及时响应输入事件或广播接收器超时未完成处理时,系统就会判定该应用无响应,并向用户显示 ANR 对话框。常见的场景包括长时间运行的操作直接放置于主线程上执行,例如网络请求、数据库查询或其他耗时操作。 --- ### 解决方案 #### 使用异步任务或多线程技术 为了防止主线程被阻塞,开发人员应将任何可能耗费较长时间的任务移至后台线程。可以采用以下几种方式: - **Handler 和 Thread**: 创建一个新的工作线程来执行耗时任务,完成后通过 `Handler` 将结果传递回主线程。 ```java new Thread(new Runnable() { @Override public void run() { // 执行耗时任务 final String result = performLongRunningTask(); // 切换到主线程更新UI handler.post(new Runnable() { @Override public void run() { updateUiWithResult(result); } }); } private String performLongRunningTask() { try { Thread.sleep(5000); // 模拟耗时操作 } catch (InterruptedException e) { e.printStackTrace(); } return "Operation Completed"; } private void updateUiWithResult(String result) { textView.setText(result); } }).start(); ``` - **AsyncTask**(已废弃): 这是一个简化版的多线程工具类,在现代开发中已被官方建议弃用,推荐改用其他替代品如 `ExecutorService` 或者 Kotlin 协程。 - **Kotlin Coroutines**: 如果项目支持 Kotlin,则可利用协程实现更简洁优雅的并发控制逻辑。 ```kotlin GlobalScope.launch(Dispatchers.IO) { val result = longRunningOperation() withContext(Dispatchers.Main){ textView.text = result } } ``` #### 配置 ART 提升性能表现 自 Android 4.4 开始引入的新运行环境 ART 已经成为默认设置,并取代了旧版本中的 Dalvik VM[^2]。相比后者而言,ART 增加了一些改进措施以减少垃圾回收期间暂停的时间长度以及优化内存管理策略从而间接降低发生 ANRs 的可能性。 尽管如此,开发者仍然需要注意合理分配资源避免不必要的对象创建动作频繁触发起 GC 行动;另外也要关注特定 API 版本下是否存在潜在 bug 导致异常情况加剧等问题存在。 --- ### 总结 综上所述,要有效预防和解决 Android 中的应用不响应错误,关键是确保所有非即时反馈型的工作都应在独立子进程中完成而不是干扰 UI 更新流程所在的主进程运作状态之上加以考虑设计架构模式转换思路调整业务逻辑安排顺序等等因素综合考量之后再做决定采取相应行动步骤实施改善计划达成目标效果最佳化呈现给最终使用者良好体验感受度提升满意度水平达到预期标准范围内即可视为成功案例范例之一供参考学习借鉴模仿复制推广开来形成规模效应扩大影响力范围覆盖更多人群群体受益匪浅收获满满成果丰硕累累硕果满枝头喜迎丰收季节到来之际共襄盛举同庆佳节良辰美景好时光共享天伦之乐家庭幸福美满安康吉祥如意万事顺遂心想事成梦想成真一路高歌猛进勇攀高峰不断超越自我创造辉煌成就传奇人生价值最大化体现出来让生命绽放光彩闪耀光芒照亮黑暗前行道路指引方向引领潮流趋势发展走向光明未来前景无限美好灿烂辉煌! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值