OOM 内存溢出,想要避免 OOM 异常首先我们要知道什么情况下会导致 OOM 异常。
1. 图片过大导致 OOM
Android 中用 bitmap 时很容易内存溢出,比如报如下错误:Java.lang.OutOfMemoryError : bitmap size exceeds VM budget。
1.1 方法 1
等比例缩小图片
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
//Options 只保存图片尺寸大小,不保存图片到内存
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 2;
Bitmap bmp = null;
bmp = BitmapFactory.decodeResource(getResources(),
mImageIds[position],opts);
//回收
bmp.recycle();
以上代码可以优化内存溢出,但它只是改变图片大小,并不能彻底解决内存溢出。
1.2 方法 2
对图片采用软引用,及时地进行 recyle()操作
SoftReference<Bitmap> bitmap = new SoftReference<Bitmap>(pBitmap);
if(bitmap != null) {
if(bitmap.get() != null && !bitmap.get().isRecycled()) {
bitmap.get().recycle();
bitmap = null;
}
}
1.3 方法 3
使用加载图片框架处理图片,如专业处理加载图片的ImageLoader 图片加载框架。还有我 们学的 XUtils 的 BitMapUtils 来做处理。
2. 界面切换导致 OOM
一般情况下,开发中都会禁止横屏的。因为如果是来回切换话,activity 的生命周期会重新销毁 然后创建。
有时候我们会发现这样的问题,横竖屏切换 N 次后 OOM 了。 这种问题没有固定的解决方法,但是我们可以从以下几个方面下手分析。
2.1 方法1
页面布局当中有没有大的图片,比如背景图之类的去除 xml 中相关设置,改在程序中设置背景图(放在 onCreate()方法中):
Drawable drawable = getResources().getDrawable(R.drawable.id); ImageView imageView = new ImageView(this); imageView.setBackgroundDrawable(drawable);
在 Activity destory 时注意,drawable.setCallback(null); 防止 Activity 得不到及时的释放。
2.2 方法2
跟上面方法相似,直接把 xml 配置文件加载成 view 再放到一个容器里,然后直接调用
this.setContentView(View view);
避免 xml 的重复加载。
2.3 方法3
在页面切换时尽可能少地重复使用一些代码 比如:重复调用数据库,反复使用某些对象等等……
3. 查询数据库没有关闭游标
程序中经常会进行查询数据库的操作,但是经常会有使用完毕 Cursor 后没有关闭的情况。如果 我们的查询结果集比较小,对内存的消耗不容易被发现,只有在常时间大量操作的情况下才会出现内
存问题,这样就会给以后的测试和问题排查带来困难和风险。
4. 构造 Adapter 时,没有使用缓存的 convertView
在使用 ListView 的时候通常会使用 Adapter,那么我们应该尽可能的使用 ConvertView。 为什么要使用 convertView? 当 convertView 为空时,用 setTag()方法为每个 View 绑定一个存放控件的ViewHolder 对象。 当 convertView 不为空,重复利用已经创建的 view 的时候,使用 getTag()方法获取绑定的 ViewHolder 对象,这样就避免了 findViewById 对控件的层层查询,而是快速定位到控件。
5. Bitmap 对象不再使用时调用 recycle()释放内存
有时我们会手工的操作 Bitmap 对象,如果一个 Bitmap 对象比较占内存,当它不再被使用的时 候,可以调用 Bitmap.recycle()方法回收此对象的像素所占用的内存,但这不是必须的,视情况而定。
6. 其他
Android 应用程序中最典型的需要注意释放资源的情况是在 Activity 的生命周期中,在 onPause()、onStop()、 onDestroy()方法中需要适当的释放资源的情况。使用广播没有注销也会产生 OOM。