目录
ANR(Application Not Responding)定义
ANR一般有三种类型:
处理办法
防患于未然
Out of Mana,法力耗尽。
这个内存的限度究竟是多少呢?
这个限制值是怎么测出来的呢?
ANR掌握这三个值:
如何调节阈值
什么情况会出现OOM呢?
防止OOM出现的一些注意点
总结
ANR(Application Not Responding)定义在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application Not Responding)对话框。用户可以选择“等待”而让程序继续运行,也可以选择“强制关闭”。
OOM - Out of Memory,内存溢出
ANR一般有三种类型:
-
KeyDispatchTimeout(5 seconds) — 按键或触摸事件在5秒内无响应
-
BroadcastTimeout(10 seconds) — BroadcastReceiver在10秒内无法处理完成
-
ServiceTimeout(20 seconds) — Service在20秒内无法处理完成
第一种类型很常见,就是你在UI线程里做了很多耗时的工作,导致UI阻塞住超过5秒,这个时候用户一定很气恼准备砸手机卖肾了,Android系统也会认为你的app做得实在是太烂了,赶紧提示用户把app结束掉,别让用户以为是安卓太烂了的缘故。
第二种也是一样,你刚刚接收到一个低电量的广播,要么赶紧弹一个框出来让用户注意电量(前台),要么赶紧开一个Service默默地杀掉耗电的app(后台),但是你若是在BroadcastReceiver里磨磨蹭蹭犹豫不决,Android系统也会认为你这个app简直是天秤座附体,赶紧回家纠结吧,别占着广播台了。
第三种比较少见,但也会出现,比如处理一些数据的时候算法不够优化,写大量文件啊,等等。
处理办法- 1和3的处理办法就是:开线程、开线程、开线程,然后用上一课我们学到的Handler去异步处理UI。
- 2的话和上文提到的一样,要么转换成1的问题或者3的问题,不要停留在Broadcast里。
耗时的操作主要是I/O操作:
-
网络请求
当你准备进行网络操作的时候,想都不要想,一定要开线程。在Android2.x的时候还允许你在主线程里进行网络请求(只要不超过ANR的5秒限制),现在的Android4.x就不要想了,连ANR的机会都不会给你,直接报异常退出。
-
文件读写
当你用java的File操作的时候当然会警觉,会想到要开线程。但是有些坑你未必就能注意到:
-
数据库操作,尤其是可能会有大量批量的数据库操作的时候。
(我表示曾经被坑过,即便你是开了线程,在大量数据库操作时的超级慢也会让人受不了,你需要搜索一下“SQLite的事务处理”,症结在这儿。
ps:不只是SQLite,数据库在批量操作的时候都需要“事务处理” 。)
-
注意SharedPreferences,由于SharedPreferences封装的很好,所以很多时候往往会忘记这东西本质上是在读写xml文件啊!
虽然一般用这种方式存储是很少的数据量,但依然不可小觑。还有个小细节也要改变一下以往的习惯:
SharedPreferences sp=context.getSharedPreferences("xxx",context.MODE_PRIVATE); SharedPreferences.Editor editor=sp.edit(); editor.putInt("num",1); // editor.commit(); 没错,旧方法是使用commit(),它是直接操作文件的 editor.apply(); //推荐使用新方法apply(),它是异步的
-
计算密集型操作
没啥说的,异步,然后优化算法吧。如果计算结果不是急需要的话可以托管给服务端来处理嘛!
总结
总而言之,ANR的存在就是在不断提醒你,优化,优化,再优化。优化效率,优化视觉,优化体验。
Out of Mana,法力耗尽。
内存就像法力,耗尽了就什么都不能做了。有时候一个应用程序占用了太大的内存,超过了Android系统为你规定的限制,那么系统就会干掉你,以保证其他app有足够的内存。俗称内存溢出(Out Of Memory)。(其实不止Android系统,内存溢出本身说的就是java虚拟机的事。)
这个内存的限度究竟是多少呢?有人说是16M,有人说是32M。事实上,这个是因系统而异的,系统又因硬件设备而异。通常来说物理RAM越大的手机,系统制作者会设置宽松一点的内存限制。
当然了,设置恰到好处的限制值也是很不容易的。拿我身边的手机做了个调查:我的烂酷派,给每个进程的内存限制是48M,而RAM同样是1G的旧华为分配了128M,魅族MX4是256M。
ps:但是呢从另一个方面讲,假设每个进程都恰好占用了满限制的内存空间,那么酷派的手机最少可以开21个进程,而华为和魅族最少只能有8个进程。虽然这样看起来21进程和8进程都挺多,但是除去后台的杀不掉的进程,从体验上讲,保证小内存的app能够运行起来,可以让多任务的体验更好一些……
这个限制值是怎么测出来的呢?直接贴代码(Activity内的代码):
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button= (Button) findViewById(R.id.ok);
final TextView text=(TextView)findViewById(R.id.text);
button.setText("查看内存");
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String str="";
str="最大可得到内存:"+Runtime.getRuntime().maxMemory()/1024/1024+"M"+"\n";
str+="目前占用内存:"+Runtime.getRuntime().totalMemory()/1024/1024+"M"+"\n";
str+="目前占用内存中空闲部分:"+Runtime.getRuntime().freeMemory()/1024/1024+"M"+"\n";
text.setText(str);
}
});
}
布局文件为一个TextView和一个Button,这里就不展示了,直接展示运行结果。
ANR掌握这三个值:-
maxMemory
最大可得到内存,指的是这个进程能从系统得到的最多的内存空间,超过这个值就会OOM。
-
totalMemory
目前该进程所占用的内存有多大,很好理解。
-
freeMemory
从字面理解很容易误解,让人以为是进程还能使用的剩余空间。其实不是这样,进程从系统挖来了totalMemoty这么大的空间,但是并没有完全使用,其中还有freeMemory这么大的空间只是挖来了,并没有实际的使用它们。等到程序真正开始使用这些空间的时候,freeMemory就开始减少,当减到0的时候就会去挖更多的空间来,依然会多挖一些来备用。以此类推,直到达到maxMemory,然后OOM,Duang~
有一个很简单有效的方法来帮助你理解这一过程,你在onClick()里除了显示之外,加上一个循环:
for(int i=1;i
关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?