解决读取bitmap内存溢出问题

官方文档解决办法:http://developer.android.com/training/displaying-bitmaps/index.html


一、有效的加载大图(Loading Large Bitmaps Efficiently)

1.读取图片的密度和类型(Read Bitmap Dimensions and Type)

BitmapFactory.Options options = new BitmapFactory.Options();

options.inJustDecodeBounds = true;  //设置为true调用BitmapFactory的decode方法不会分配内存,返回一个空的bitmap

BitmapFactory.decodeResource(getResources(), R.id.myimage, options);  //返回为null  ,不分配内存

int imageHeight = options.outHeight;   //图片的高度

int imageWidth = options.outWidth;    //图片的宽度

String imageType = options.outMimeType;  //图片的类型

根据图片的高度和宽度可以计算出图片的密度,是否大于系统要求的内存,防止内存溢出,然后设置options.inJustDecodeBounds = false;

否则用BitmapFactory生成的Bitmap返回值为null


2.加载缩小的图片到内存(Load a Scaled Down Version into Memory)

options.inSampleSize = 3;  通过BitmapFactory得到的Bitmap宽度是原图的1/3,高度也是原图的1/3。



二、脱离UI线程(Processing Bitmaps Off the UI Thread)

使用AsyncTask,在主线程中加载大量图片会导致,看起来机子很卡

class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {

    private final WeakReference<ImageView> imageViewReference;

    private int data = 0;



    public BitmapWorkerTask(ImageView imageView) {

        // Use a WeakReference to ensure the ImageView can be garbage collected

        imageViewReference = new WeakReference<ImageView>(imageView);  //使用弱引用

    }



    // Decode image in background.

    @Override

    protected Bitmap doInBackground(Integer... params) {

        data = params[0];

        return decodeSampledBitmapFromResource(getResources(), data, 100, 100));  //返回得到的图片

    }



    // Once complete, see if ImageView is still around and set bitmap.

    @Override

    protected void onPostExecute(Bitmap bitmap) {

        if (imageViewReference != null && bitmap != null) {

            final ImageView imageView = imageViewReference.get();  

            if (imageView != null) {    //由于是弱引用判断是否被回收再设置图片

                imageView.setImageBitmap(bitmap);

            }

        }

    }

}



//-----------------------------------使用AsyncTask异步加载图片

public void loadBitmap(int resId, ImageView imageView) {

    BitmapWorkerTask task = new BitmapWorkerTask(imageView);

    task.execute(resId);

}


三、缓存Bitmap(Caching Bitmaps)

1、使用内存缓存LruCache类(Use a Memory Cache)

2.3以后垃圾回收器,对于回收软引用和弱引用越来越厉害,往往,程序离out of memory 还很早弱引用或者软引用就被回收了。。

所以不建议使用软引用和弱引用。

下面的例子是使用 LruCache加载Bitmap

private LruCache<String, Bitmap>  mMemoryCache;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(new MyView(this));

int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024);

int cacheSize = maxMemory/8;  //缓存

mMemoryCache = new LruCache<String, Bitmap>(cacheSize){



@Override

protected int sizeOf(String key, Bitmap value) {

return value.getByteCount()/1024;  //缓存的大小 ,兆为单位

}

};

}

//往内存缓存中加入图片

public void addBitmapToMemoryCache(String key,Bitmap bitmap){

mMemoryCache.put(key, bitmap);

}

//通过key得到Bitmap

public Bitmap  getBitmapFromMemoryCache(String key){

return mMemoryCache.get(key);

}

    public void  loadImage(int resId ,ImageView mImageView){

    final String imageKey = String.valueOf(resId);

        final Bitmap bitmap = getBitmapFromMemoryCache(imageKey);

        if (bitmap != null) {

            mImageView.setImageBitmap(bitmap);

        } else {

            mImageView.setImageResource(R.drawable.image_placeholder);//设置默认图片

            //异步加载图片

            BitmapWorkerTask task = new BitmapWorkerTask(mImageView);

            task.execute(resId);

           

        }

    }



2、使用磁盘缓存(Use a Disk Cache)

public static File getDiskCacheDir(Context context, String uniqueName) {

   

    final String cachePath =

            Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||

                    !isExternalStorageRemovable() ? getExternalCacheDir(context).getPath() :

                            context.getCacheDir().getPath();



    return new File(cachePath + File.separator + uniqueName);

}


四、管理Bitmap内存(Managing Bitmap Memory)

五、显示Bitmap到你的UI(Displaying Bitmaps in Your UI)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值