OOM异常产生的原因和处理方法
一般而言,android中常见的原因主要有以下几个:
1.数据库的cursor没有关闭。
2.构造adapter没有使用缓存contentview。
3.调用registerReceiver()后未调用unregisterReceiver().
4.未关闭InputStream/OutputStream。
5.Bitmap使用后未调用recycle()。
6.Context泄漏。
7.static关键字等。
接下来分别对这些溢出情况说出解决的思路:
1.针对数据库cursor没有关闭的情况,如果我们查询数据库得到的数据量比较小的话是不会造成内存溢出的,但是如果太大的话就容易发生这种异常,所以当我们在使用完Cursor的时候就应该手动调用它的close方法关闭cursor.
2.针对adapter没有复用convertView的情况,在我们开发的过程中,经常会遇到一个listview加载成百上千条的数据,如果不复用convertView的话就会在每次执行getView方法的时候都创建一个新的对象,而这个方法的调用速度又是很快的,java不能够及时的回收内存就会造成OOM异常,这时候除了要在getView方法里面对convertView进行判断后复用,还应该使用ViewHolder类来保存通过过findViewById得到的子控件地址值.
3.在activity中注册了广播,但是在activity退出的时候没有取消注册的话可能会造成内存溢出,需要手动的在相应的位置进行反注册.
4.不关闭输入输出流的话就相当于在内存和硬盘一直存在着连接占用着资源,当其他操作需要资源时就会造成内存溢出.
5.位图在安卓中占用的内存是很大的,使用后如果不及时回收的话会占用大量空间,所以针对位图的操作一般有如下解决方案:
1)及时的调用resycle方法来手动的回收;
2)设置采样率,有时候我们不一定要把图片完全显示出来,这时候就要按比例来缩放,在我们得到采样率的时候就可以将图片缩小后再进行加载,节省大量的内存;
3)使用软引用.
6.上下文泄露
例如在activity中使用了线程内部类,这时候在线程内存就会保存一个activity的引用,当activity被销毁的时候,线程仍在执行的话就容易造成oom,因为此时的activity的引用仍然存在没有被释放,那么这个activity就仍然没有从内存中被gc.
7.static关键字
开发中使用关键字static可以将成员变量和方法变成类变量和类方法,这样会大大延长变量的生命周期,如果我们过多的使用static来保存占用资源过多的对象的引用就会造成内存溢出,比如用static修饰一个上下文的对象的话.
第一,应该尽量避免static成员变量引用资源耗费过多的实例,比如Context。
第二、Context尽量使用Application Context,因为Application的Context的生命周期比较长,引用它不会出现内存泄露的问题。
第三、使用WeakReference代替强引用。比如可以使用WeakReference<Context> mContextRef;