ANR
App的相应是由Activity Manager和WindowManager系统服务负责监控的.
运行在主线程的典型方法.
Activity的生命周期, Service的生命周期, BroadcastReceiver的onReceive()方法, AsyncTask中的除了doInBackground()方法的其他方法.
OOM
定义: 当前App占用的内存 加上 我们要申请的内存 大于 dalvik 虚拟机限制的最大内存数时, 就会报out of memory error, 导致App 崩溃.
几个容易混淆的内存问题的概念
内存溢出, 指的就是OOM.
内存抖动, 指的是短时间内创建了大量的对象, 而这些对象又会通过gc()快速的被释放, 占用了大量的内存空间, 内存占用值短时间内大小波动的幅度很大. 这就叫内存抖动.
内存泄露. 无用对象还被gc root所引用, 导致无法通过gc()回收掉这些无用对象, 这就是内存泄露.
解决OOM 的几种典型方法
有关bitmap
- 按需要的尺寸加载图片, 使用inSampleSize参数来指定缩放比例.
- 及时释放内存. Bitmap的构造方法都是私有的, 创建bitmap对象都是通过BitmapFactory来完成的. bitmap对象的创建都是通过调用JNI方法完成的.
因此bitmap对象占用的内存分2部分, 一部分是java内存, 另一部分是C内存.这些C内存就需要开发人员手动调用recycle()方法去释放. - 使用inBitmap属性.
首先要明白, inBitmap这个public的属性的类型是Bitmap.
public class BitmapFactory {
public static class Options {
public Bitmap inBitmap;
}
}
github上有一个GlideBitmapPool的项目的主要目的就是使用inBitmap这个属性.
大致的使用思路是:
当使用完一个bitmap后, 不去像原来那样调用recycle()回收, 而是调用GlideBitmapPool.putBitmap(bitmap);把这个对象放入对象池.
当下次再要创建新的bitmap时, 首先调用
Bitmap bitmap = GlideBitmapPool.getBitmap(width, height, config);
得到一个空的对象.
然后把这个空对象设置给inBitmap属性, 然后再去解析图片的时候传入这个bitmap对象, 创建图片对应的bitmap对象. 这样, 这个新bitmap对象的创建过程就不用申请新的内存了, 避免了gc()频繁的被调用.
实际上, 成熟的图片加载框架, 如glide已经采用了这种方法.
glide的读法是g"爱"d.
商业项目中的生产代码基于效率的考虑, 要使用glide库来做图片加载, 不要直接使用BitmapFactory.decodeFile().来做图片加载.
实例化bitmap时, 手动去捕获out of memory error, 避免崩溃.
使用多进程化解主进程的内存压力.
其他方法:
ListView中使用ConvertView, 避免在onDraw()方法中创建新的对象, 减少内存抖动.
--- DONE. ---