照片墙由于涉及多图加载,很容易造成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; } }
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; }
ImageView photo = (ImageView) mImgWall.findViewWithTag(imginfo_task);
详细可以参考源码 saberhao的照片墙
谢谢~