Android照片墙实现 -- 图片加载,防止OOM的处理办法

照片墙由于涉及多图加载,很容易造成OOM,或者系统卡顿,我们主要是用了下面三个方法来避免

1. 按比例缩减图片尺寸

2.使用Cache缓存技术

3. 多线程加载

下面我们通过代码详细介绍~

1. 按比例缩减图片尺寸

	private Bitmap getBitmapFromMemoryCache(Uri uri,Context context) {
		// TODO Auto-generated method stub
		ContentResolver cr = context.getContentResolver();
		try {
			BitmapFactory.Options options = new BitmapFactory.Options();
			options.inJustDecodeBounds = true;
			BitmapFactory.decodeStream(cr.openInputStream(uri), null, options);
	        options.inSampleSize = 4;//图片宽高都为原来的四分之一,即图片为原来的十六分之一
			options.inJustDecodeBounds = false;  
			options.inDither = false;
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
			Bitmap bitmap = BitmapFactory.decodeStream(cr.openInputStream(uri), null, options);
			return bitmap;
			
		}catch (FileNotFoundException exp)
		{		
			exp.printStackTrace(); 
			return null;
		}
	}

再Cache中获取图片,然后长宽都缩减为原来的1/4,像素可以缩减为1/16,大大介绍加载时间


2.使用Cache缓存技术

int maxMemory = (int) Runtime.getRuntime().maxMemory();  
        int cacheSize = maxMemory / 8;  
        // 设置图片缓存大小为程序最大可用内存的1/8  
        mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {  
            @Override  
            protected int sizeOf(String key, Bitmap bitmap) {  
                return bitmap.getByteCount();  
            }  
        };
使用cache缓存,分配最大内存的1/8作为缓存区,存放图片,减少图片加载开销


3. 多线程加载

很明显的一点,是我们不能再主线程加载多图,这样很容易产生OOM,所以我们使用后台线程进行加载图片

定义加载图片线程

private Set<BitmapWorkerTask> taskCollection;

线程加载图片工作,当加载完毕,将任务移除

public class BitmapWorkerTask extends AsyncTask<ImgInfo, Void, Bitmap> {
	
    	ImgInfo imginfo_task;
		@Override
		protected Bitmap doInBackground(ImgInfo... params) {
			// TODO Auto-generated method stub
			imginfo_task = params[0];
			// 从SD卡获取bitmap
            Bitmap bitmap = LoadImage(params[0]);   
            return bitmap; 
		}
		
		 @Override  
	        protected void onPostExecute(Bitmap bitmap) {  
	            super.onPostExecute(bitmap);  
	            // 根据Tag找到相应的ImageView控件,将下载好的图片显示出来。  
	            ImageView photo = (ImageView) mImgWall.findViewWithTag(imginfo_task); 
	            
	            if (photo != null && bitmap != null) {
	            	photo.setImageBitmap(bitmap);  
	            }  
	            //移除任务
	            taskCollection.remove(this);  
	        }  

    }


最后还有需要注意的一点,我们必须给View一个tag, 让View 可以找到对应的图片信息

public View getView(int position, View convertView, ViewGroup parent) {
		imginfo = imginfos.getItemAt(position);
		View view;
	    ImageView photo;
		if(convertView == null)
		{
			view = LayoutInflater.from(context).inflate(R.layout.pic_layout, null);		
			photo = (ImageView)view.findViewById(R.id.photo);
			photo.setTag(imginfo);
		}else{	
			view = convertView;
			photo = (ImageView)view.findViewById(R.id.photo);
			photo.setTag(imginfo);
			
		}
		loadBitmaps(imginfo, photo);
		return view;
	}

通过 ImgInfo 就 找到对应的View

 ImageView photo = (ImageView) mImgWall.findViewWithTag(imginfo_task); 

这样图片就不会有乱序的情况,一人一个坑 =。=


详细可以参考源码 saberhao的照片墙 


谢谢~





你可能感兴趣的:(oom,图片,LruCache)