ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ANR异常面试详解

2019-09-20 16:39:28  阅读:242  来源: 互联网

标签:当中 耗时 主线 面试 详解 线程 ANR 操作


大家好,今天我来给大家讲讲,在面试当中遇到anr的面试问题.

一、什么是anr?

在安卓当中,如果我们的应用程序有一段时间点击不够灵敏,系统就会向用户显示一个对话框,这个对话框的内容就是anr,也就是 Application  Not  Responding,他就是可以让用户选择等待,可以让程序继续运行.同时你也可以选择关闭.所以说,对于一个流畅的用户体验良好的,一个合理的App当中,是绝对不能出现ANR的,如果你出现ANR就势必让用户处理对话框,而这个对话框是十分影响体验的.在默认的情况下,在一个Activity当中,最长的执行时间是5秒,如果超过了5秒没有做出响应,n那就会出现这个Anr弹框.

而在Broadcast Receiver广播接收者当中,最长的执行时间是10秒,你可以在10秒钟之内做出一些操作,如果超出10秒还没有完成,就会造成ANR,总的来说,ANR如果在面试当中,面试官问你ANR是什么,你就可以这样回答:Anr就是一个应用程序无响应的对话框.

二、造成anr的主要原因

       我们知道在应用程序当中,它的响应性是由Activity   Manager和WindowManager系统服务监视的.当它监测到刚才所说的Activity 和Broadcast Receiver当中5秒,10秒钟,没有执行完任务之后,安卓就会弹出ANR的对话框.其实造成ANR的主要原因有以下两点:

   1.主线程被IO操作(从4.0之后网络IOb不允许在主线程中)阻塞

   2.主线程中存在耗时的计算

比如网络数据的读取,还有如果你在主线程中开启了线程,做了耗时操作,也会造成ANR.其实这两个原因,归根到根本都是在主线程当中做了非常耗时的操作,就像刚才所说的下载,IO流的读取等等.所以说你尽量要把那些耗时的网络,数据库的读取操作,高耗时的一些计算,都应该放在子线程里面来完成.然而不是说你的主线程阻塞在那里等待子线程完成,就是说调用那个thread,wait,sleep方法.而是我们可以用安卓当中一个方便的机制,叫做handler机制来让子线程的消息传递给子线程来进行耗时操作的转移,把耗时操作转移到子线程当中,而让主线程处理一些UI的操作,在安卓里这个机制叫做handler机制,刚才在提到ANR的主要原因的时候,提到避免ANR最主要的一点就是不能在主线程当中进行耗时操作.   那么在安卓当中那些操作是在主线程里面?我给大家总结了以下几点:

Activity的所有生命周期回调都是执行在主线程的.

Service默认是执行在主线程的.

这和大家的某些观念有些不一样,有人认为service是一个服务,服务应该能做一些后台的耗时操作,其实不然,安卓系统当中规定了,service默认执行操作也只能都是在主线程,如果你要进耗时操作,它会弹出anr弹框,同时如果你想在service里面做耗时操作,你可以启用安卓里面另外一个机制,叫做IntentService,它里面可以做耗时操作.

Broadcast Receiver的onReceive回调是执行在主线程的.(所以onReceive里面你也不能做耗时操作)

没有使用子线程的looper的Handler的handkeMessage,post(Runnable)是执行在主线程的. 

它是说没有关联子线程的looper,所以说它这里的handler关联的是主线程的looper,所以说它的任务都是执行在主线程的

AsyncTask的回调中除了doInBackground,其它都是执行在主线程.

doInBackground字面理解它也是做一些在后台的操作.

我们知道在安卓当中以下两种情况会弹出ANR对话框,第一个是在五秒内,你无法响应用户的输入事件,比如在Activity,在service里面,第二种就是Broadcast Receiver十秒钟之内无法结束,它会弹出ANR对话框.而造成以上两种的主要原因就是在主线程当中,做了太多的耗时操作.所以说为了避免ANR,尽量不要在主线程当中做耗时操作,给用户良好的体验.

三、如何解决anr 

1.可以使用Asynctask处理耗时IO操作.

我们知道Asynctask它是一个灵活的切换子线程到UI线程的机制,

2.使用Thread或者HandlerThread提高优先级

我们知道Thread和HandlerThread都能开启一个子线程,但是有区别的就是后者HandlerThread它在子线程当中可以创建Handler来发送消息因为它内部创建了Looper关联了一个消息队列,所以说它能创建Handler.而在子线程thread里面不可以创建Handler.注意一定要提高优先级,如果不提高优先级,Thread或者HandlerThread的优先级和主线程是一样,所以说仍然会造成ANR.

3.使用handler来处理工作线程的耗时任务

handler它可以让子线程灵活的发送消息到主线程,来处理一些耗时异步的任务

4.Activity的onCreate和onResume回调中尽量避免耗时的代码

我们知道,Activity所有生命周期回调方法都是执行在主线程的,所以它的回调方法里面,不要做耗时操作. 

标签:当中,耗时,主线,面试,详解,线程,ANR,操作
来源: https://blog.csdn.net/qq_42014702/article/details/101060956

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有