Osheep

时光不回头,当下最重要。

Android异常和性能优化 - ANR异常

一.什么是ANR

在Android中,如果程序有一段时间点击不够灵敏,系统就会给用户弹出一个对话框,对话框的内容就是ANR,它是Application Not Responding的缩写,即应用程序无响应。它可以让用户选择“等待”,而让程序继续进行,也可以选择“关闭”。在一个流畅的用户体验良好的APP中是绝对不能出现ANR的,因为如果出现ANR,就会让用户去处理这个对话框。而这个对话框是十分影响体验的。在默认情况下在Activity当中最长的执行时间是5秒,如果超过了5秒没有做出相应,那就会出现ANR的弹框,而在BroadcastReceiver(广播机制)当中最长的执行时间是10秒,可以在10秒之内进行操作,如果超出10秒还没有完成就会造成ANR。

二.造成ANR的原因

在应用程序当中,应用程序的响应性是有Activity Manager和WindowManager系统服务监视的。当它监测到Activity5秒,BroadcastReceiver10秒内没有执行完操作时,android就会弹出ANR的对话框。

造成ANR的主要原因有以下两点:

1.主线程中做了耗时的IO操作,主线程被IO操作阻塞(android4.0后网络操作不能在主线程中,会直接抛出异常)
2.主线程中存在耗时的计算。(如一些网络数据的读取等等,如果在主线程中开启了线程做了耗时操作也会造成ANR)

这两个原因从根本上来说都是在主线程中做了耗时的操作,所以要尽量把那些耗时的网络或数据库读取操作,高耗时的计算都应该放在子线程里来完成。然而,不是说你的主线程阻塞在那里等待子线程的完成,也不是调用 Thread.wait()或是Thread.sleep()。而是用android当中的Handler机制,来让子线程的消息传递给主线程。来进行耗时操作的转移,把耗时操作转移到子线程当中。而让主线程来处理一些UI的操作。

避免ANR最主要的一点就是不能在主线程中进行耗时操作。
Android中在主线程的操作:

1.Activity的所有生命周期回调都是执行在主线程的。
2.Service默认是执行在主线程的。(想在Service中进行耗时操作可以用IntentService)
3.BroadcastReceiver的onReceive回调是执行在主线程的。
4.没有使用子线程的looper的Handler的handlerMessage,post(Runnable)是执行在主线程的(没有关联子线程的looper说明使用的是主线程的looper)
5.AsyncTask的回调中除了dolnBackground,其他都是执行在主线程。(dolnBackground从字面意思上就是做后台操作)

三.如何解决ANR

1.使用Asynctask处理耗时操作(IO,网络读取等),Asynctask是一个灵活的切换子线程到UI线程的机制。
2.使用Thread或者HandlerThread提高优先级。(Thread和HandlerThread都能开启一个子线程(HandlerThread在子线程中可以创建Handler来发送消息,因为它的内部创建了looper和一个消息队列))如果不提高优先级,就会和主线程的优先级是一样的,仍然会造成ANR。
3.使用Handler来处理工线程的耗时任务。
4.Activity的onCreate和onResume回调中尽量避免耗时的任务。

点赞