照片墙由于涉及多图加载,很容易造成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的照片墙
谢谢~