第八章 ANR OOM 面试问题的讲解

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

  1. 按需要的尺寸加载图片, 使用inSampleSize参数来指定缩放比例.
  2. 及时释放内存. Bitmap的构造方法都是私有的, 创建bitmap对象都是通过BitmapFactory来完成的. bitmap对象的创建都是通过调用JNI方法完成的.
    因此bitmap对象占用的内存分2部分, 一部分是java内存, 另一部分是C内存.这些C内存就需要开发人员手动调用recycle()方法去释放.
  3. 使用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().来做图片加载.

  1. 实例化bitmap时, 手动去捕获out of memory error, 避免崩溃.

  2. 使用多进程化解主进程的内存压力.

  3. 其他方法:
    ListView中使用ConvertView, 避免在onDraw()方法中创建新的对象, 减少内存抖动.

--- DONE. ---

你可能感兴趣的:(第八章 ANR OOM 面试问题的讲解)