关于引用本地资源图片 造成OOM的解决方案

情景

在实际开发中,我们会常常使用到本地的UI,这些是固定功能的导航索引,例如一个GridView的导航界面。
最近的一个项目就出现了这样的情况,在不使用第三方图片框架的情况下,解决这个问题.

解决方案:


  1. BitmapFactory.decodeStream(InputStream, null, BitmapFactory.Options);

原先我们使用的ImageView.setBackgroundResource/setImageResource , 这些方法,都会使用Java层的createBitmap来创建一个Bitmap,意味着会消耗更多内存。
BitmapFactory.decodeStream,则是直接调用JNI nativeDecodeAsset(),而不再通过Java层,从而节省了Java层的内存空间,有效地防止了OOM的异常。
    public static Bitmap getBitmapFromRecource(Context context, int resId) {
            BitmapFactory.Options opt = new BitmapFactory.Options();
            opt.inPreferredConfig = Bitmap.Config.RGB_565;
            opt.inPurgeable = true;
            opt.inInputShareable = true;
            // 获取资源图片
            InputStream is = context.getResources().openRawResource(resId);
            return BitmapFactory.decodeStream(is, null, opt);
        }

2.出现OOM的原因之一是使用过多资源,没有及时释放.

在当前Activity中,将使用到底Bitmap对象,存储到一个集合中,在该Activity销毁的时候,释放这些资源。

所以,我们可以重载该方法,List的创建:只有当你需要引用到多个ResourceDrawable的时候.

/**
     * 根据ResourceId获取Bitmap对象,并插入到Bitmap集合中;
     * 
     * @param context
     * @param bitmapList
     * @param resId
     * @return
     */
 public static Bitmap getBitmapFromRecource(Context context, List bitmapList, int resId) {
        BitmapFactory.Options opt = new BitmapFactory.Options();
        opt.inPreferredConfig = Bitmap.Config.RGB_565;
        opt.inPurgeable = true;
        opt.inInputShareable = true;
        // 获取资源图片
        InputStream is = context.getResources().openRawResource(resId);
        Bitmap bitmap = BitmapFactory.decodeStream(is, null, opt);
        insertBitmap(bitmapList, bitmap);
        return bitmap;
    }

/**
     * 将当前的Bitmap插入到List中
     * 
     * @param bitmapList
     * @param bitmap
     * @return
     */
    private static void insertBitmap(List bitmapList, Bitmap bitmap) {
        if (!bitmapList.contains(bitmap)) {
            bitmapList.add(bitmap);
        }
    }

3.最后,在Activity销毁的时候,要对所有当前Activity使用到的Bitmap进行回收.

/**
     * 当不再使用到的时候,回收所有的Bitmap
     * 
     * @param bitmapList
     */
    public static void recycleBitmapUnuseful(List bitmapList) {
        if (null != bitmapList && 0 != bitmapList.size()) {
            for (Bitmap bitmap : bitmapList) {
                bitmap.recycle();
            }
            bitmapList.clear();
            bitmapList = null;
        }
    }


@Override
    protected void onDestroy() {
        recycleBitmapUnuseful(bitmapList);
        super.onDestroy();
    }

本文仅限于学习交流,不足之处,请踊跃指出,欢迎来喷.

你可能感兴趣的:(Android)