Android ANR错误的原因以及解决方法(Application Not Responding)

一. ANR (Application Not Responding)是什么: 

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

    


ANR 弹窗


二.ANR出现的原因:

  • 按键或触摸事件 5s 内无响应;
  • BroadcastReceiver 10s 内无法处理完成;
  • Service 在 20s 时间内无法处理完成;

发生 ANR 基本上都会出现无法响应对话框,除了一些后台程序的 ANR,造成 ANR 的原因很多,比如:

  • UI 主线程被其他操作阻塞
  • 主线程存在耗时操作(本地 IO操作、网络访问、循环等);

三.如何分析ANR

1、CPU 问题

  • Monkeylog.log 文件中定位到 "anr in" 位置,查看 cpu usage  total 占用,如发现接近100%,暂时判断为 cpu 问题。
  • 然后在 logcat.log 文件中定位到 "not responding" 发生时间,并截取
    cpuinfo.log 中时间点前后 5s 的 log,然后计算 CPU 占中,看哪个进程用的多,在酌情分析模块的 CPU 占中。

2、GC 问题

  • 定位到 logcat.log 文件中 "not responding" 发生时间点;

  • 去查看发生 ANR 时间点对应的 trace 文件,定位到应用报名,若Dalvik Thread主线程显示“SUSPENDED”,则为内存问题

  • 截取 ANR 发生时间点前 5s 的 log,分析 "dalvikvm" 打印的 Paused GC 耗时,如果过多则定位为 GC 问题,需要查看这 5s 件发生了哪些耗时的操作。

注意:发生 GC 的进程 id 需要和当前发生 ANR 的线程 id 的要一致

四.如何避免ANR

  • 合理使用 UI 主线程,耗时操作放入其他线程工作;
  • 合理使用 Handler 异步消息处理机制来处理其他线程请求。
  • 合理使用并遵循 Android 生命周期, 避免在 onCreate() and onResume()做过多的事情;
  • 使用一些架构形成规范来避免内存问题,例如:MVP、RxJava;
  • 经常使用工具来检查内存问题,例如:MAT、TraceView、AS 自带等工具;
  • 避免加载大图片引起内存不足导致 ANR;
  • 避免内存泄露引起的 ANR。


 五.总结与额外注意

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

面试可能会问到:如何快速找到ANR的原因

答:Log和trace文件。 (答案仅供参考)

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ANRApplication Not Responding)是Android系统中常见的错误,指的是应用程序无响应。当应用程序在主线程上执行一些耗时操作而没有及时返回时,系统会自动弹出ANR对话框。 为了捕获ANR错误并及时处理,可以采取以下几种方法: 1. 使用StrictMode工具:StrictMode是一种开发工具,可在开发过程中检测和报告主线程方面的违规行为。可以通过在Application类的onCreate方法中开启StrictMode来检测主线程中的耗时操作,并在发现违规时进行相应的处理。 2. 使用Handler机制:在进行耗时操作时,可以使用Handler机制将该操作放在子线程中执行,然后通过Handler发送消息将结果返回给主线程。这样可以避免主线程被阻塞,提高应用的响应性能。 3. 使用AsyncTask类:AsyncTask是Android提供的一种异步任务处理机制,可以方便地在后台执行耗时操作,并将结果传递给主线程。通过重写AsyncTask的doInBackground方法来执行耗时操作,在处理结果时可以重写onPostExecute方法更新UI界面。 4. 使用线程池:使用线程池可以管理线程的创建和销毁,避免因频繁创建线程导致的性能问题。可以使用ThreadPoolExecutor类创建一个线程池,并将耗时操作放在线程池中执行。 无论采用哪种方法,重要的是避免在主线程上执行耗时操作,确保应用程序的响应性能。另外,还可以通过分析ANR错误产生的原因,优化代码和算法,减少耗时操作的时间,提高应用的性能和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值