首页 > 代码库 > android 内存管理研究

android 内存管理研究

1. 内存管理基础知识

http://www.cnblogs.com/xingfuzzhd/p/3485924.html

 

 

  • 1. mImageView.setImageResource(R.drawable.my_image); 这段代码会调用 BitmapFactory.decodeStream() 生成一个 Bitmap。所以不要以为它比自己创建 Bitmap 节省内存。

 

3.  实际测试:

我使用了多种调用图片的方法来测试:

第一种:

// 直接载入资源 id
ImageView image = (ImageView) findViewById(R.id.imageView1)

第二种:

创建一个函数,根据 id 载入图片。杀死 Activity 时回收 Bitmap

public BitmapDrawable getImageBitmap(int idImage) {
  Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), idImage);
  images.add(bitmap);
  return new BitmapDrawable(context.getResources(), bitmap);
}

第三种:

创建一个类

/**
 * solution for OOM ------> compress bitmap
 */
public class BitmapUtils {
    private static final String TAG = "BitmapUtils";
    /**
     * calulate the compress rate
     */
    private static int calculateInSampleSize(BitmapFactory.Options opts,int reqHeight,int reqWidth) {
        if(opts == null) {
            return -1;
        }
        int width = opts.outWidth;
        int height = opts.outHeight;
        
        int sampleSize = 1;
        
        if(width > reqWidth || height > reqHeight) {
            int heightRatio = (int) (height/(float)reqHeight);
            int widthRatio = (int) (width/(float)reqWidth);
            sampleSize = (heightRatio > widthRatio) ? widthRatio : heightRatio;
        }
        return sampleSize;
    }
    
    /**
     * compress an image refer to the goal dimension
     * @param res
     * @param resId
     * @param reqWidth
     * @param reqHeight
     * @return Bitmap
     */
    public static Bitmap decodeSampledBitmapFromResource(Resources res,int resId,int reqWidth,int reqHeight) {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, opts);
        int sampleSize = calculateInSampleSize(opts, reqHeight, reqWidth);
        Log.i(TAG,"before[width:"+opts.outWidth+",height:"+opts.outHeight+"]");
        opts.inJustDecodeBounds = false;
        opts.inSampleSize = sampleSize;
        /* newly added */
        opts.inPreferredConfig = Bitmap.Config.RGB_565;
        opts.inPurgeable = true;
        opts.inInputShareable = true;
        /* newly added */
        Log.i(TAG,"insamplesize="+sampleSize);
        Bitmap bitmap = BitmapFactory.decodeResource(res, resId, opts);
        Log.i(TAG,"after[width:"+bitmap.getWidth()+",height:"+bitmap.getHeight()+"]");
        return bitmap;
    }

    /**
     * compress an image refer to the goal dimension
     * 
     * @param data image byte array
     * @param reqWidth
     * @param reqHeight
     * @return
     */
    public static Bitmap decodeSampledBitmapFromByteArray(byte[] data,int reqWidth,int reqHeight) {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(data, 0, data.length, opts);
        Log.i(TAG,"before[width:"+opts.outWidth+",height:"+opts.outHeight+"]");
        opts.inSampleSize = calculateInSampleSize(opts, reqHeight, reqWidth);
        Log.i(TAG,"insamplesize="+opts.inSampleSize);
        opts.inJustDecodeBounds = false;
        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opts);
        Log.i(TAG,"after[width:"+bitmap.getWidth()+",height:"+bitmap.getHeight()+"]");
        return bitmap;
    }
    
    public static Bitmap decodeResourceWithLowMemory(Context context, int resId) {  
        BitmapFactory.Options opt = new BitmapFactory.Options();  
        // Bitmap.Config.ALPHA_8,Bitmap.Config.ARGB_4444,Bitmap.Config.RGB_565  
        // 设置这几个参数效果都差不多,确实相当省内存啊,而且还跟原图清晰度相当  
        opt.inPreferredConfig = Bitmap.Config.RGB_565;
        opt.inPurgeable = true;
        opt.inInputShareable = true;
        return BitmapFactory.decodeResource(context.getResources(), resId, opt);  
    }
    
    public static Bitmap loadToImageViewFromResource(Resources res,int resId,ImageView imageView) {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, opts);
        int reqHeight = imageView.getLayoutParams().height;
        int reqWidth = imageView.getLayoutParams().width;
        int sampleSize = calculateInSampleSize(opts, reqHeight, reqWidth);
        Log.i(TAG,"before[width:"+opts.outWidth+",height:"+opts.outHeight+"]");
        opts.inJustDecodeBounds = false;
        opts.inSampleSize = sampleSize;
        /* newly added */
        opts.inPreferredConfig = Bitmap.Config.RGB_565;
        opts.inPurgeable = true;
        opts.inInputShareable = true;
        /* newly added */
        Log.i(TAG,"insamplesize="+sampleSize);
        Bitmap bitmap = BitmapFactory.decodeResource(res, resId, opts);
        Log.i(TAG,"after[width:"+bitmap.getWidth()+",height:"+bitmap.getHeight()+"]");
        return bitmap;
    }

}

 

4. 测试过程:

创建两个 Activity,每个都载入几个大图片,然后两个 Activity 之间不停的切换。

第一种方法,切换多次后 OOM (out of memory)。 第二种方法,更快的 OOM。

第三种,如果压缩率够高的话,几乎不会 OOM。比如原始图片为 2048 * 1600,然后目标 ImageView 的大小为 200* 150。最后内存消耗将大大减小。然后如果

两者分辨率差距不大,最后内存消耗将不会被优化,最后也将 OOM。