网上有很多例子介绍 ImageSwitcher 和 Gallery 配合浏览图片(其实看起来都是从一个来源拷贝的),大部分都有两个问题:
1、只讲了如何浏览应用内置资源,而没有给出浏览SD卡上图片的方法;
2、没有提到实际应用中会碰到的问题,就是内存不足的异常。
其中第一个问题有少数例子提到了解决方法,而第二个问题迄今为止尚未看到有人讨论。本人参考了一些资料,找到一种解决方法如下:
- 首先让自定义的ImageAdapter保存一个图片目录路径,用File.listFiles() 方法列出所有图片文件(根据需要,可能要排除一些非图片文件);
- 在需要时用 BitmapFactory.decodeFile() 解码出图片 的位图,在ImageAdapter 的 getView方法中,用ImageView.setImageBitmap()方法指定图片的位图;
- 将解码出的图片Bitmap用SoftReference保存,作为缓存,并便于系统需要内存时能够自动释放;
- 在Gallery 的 OnItemSelectedListener.onItemSelected() 方法中,不用ImageSwitcher.setImageURI方法,而是尝试从缓存中提取图片位图(这一点很关键!),设置ImageSwitcher中的ImageView。
参考代码:
public class ImageAdapter extends BaseAdapter {
private Context mContext;
private String imgFolder;
List<File> imgFileList = new ArrayList<File>();
List<SoftReference<Bitmap>> imageRefLst = new ArrayList<SoftReference<Bitmap>>();
List<SoftReference<Bitmap>> thumbRefLst = new ArrayList<SoftReference<Bitmap>>();
BitmapFactory.Options bfOpt;
public ImageAdapter(Context c,String asImageFolder) {
mContext = c;
imgFolder = asImageFolder;
imgFileList.addAll(Arrays.asList(new File(imgFolder).listFiles()) );
for (File f:imgFileList){
if (".nomedia".equals(f.getName())){
imgFileList.remove(f);
break;
}
}
Log.d(LOG_TAG, "Image count :"+imgFileList.size());
//防止大图片内存不足
bfOpt = new BitmapFactory.Options();
// bfOpt.inTempStorage = new byte[1024*1024*10]; //10MB的临时存储空间
bfOpt.inSampleSize = 4;
}
public int getCount() {
return imgFileList.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
ImageView imgView;
if (convertView !=null && convertView instanceof ImageView){
imgView = (ImageView) convertView;
}else{
imgView = new ImageView(mContext);
imgView.setAdjustViewBounds(true);
imgView.setLayoutParams(new Gallery.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
imgView.setImageBitmap(getImage(position));
// i.setBackgroundResource(R.drawable.e);
}
return imgView;
}
public Bitmap getImage(int position)
{
return getImageFromList(imageRefLst,position);
}
public Bitmap getImageThumb(int position)
{
return getImageFromList(thumbRefLst,position);
}
private Bitmap getImageFromList(List<SoftReference<Bitmap>> imgRefLst,int position)
{
Bitmap img = null;
//First get it from cache
if (position>=0 && position<imgRefLst.size() && imgRefLst.get(position)!=null )
img = imgRefLst.get(position).get();
if (img==null){
Log.d(LOG_TAG,"Loading image:"+imgFileList.get(position));
if (imgRefLst == imageRefLst){
bfOpt.inSampleSize = 1;
}else{
bfOpt.inSampleSize = 8;
}
img = BitmapFactory.decodeFile(imgFileList.get(position).getAbsolutePath(),bfOpt); //这里bfOpt为Options属性
imgRefLst.add(position, new SoftReference<Bitmap>(img));
}
return img;
}
}
OnItemSelectedListener.OnItemSelected():
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id)
{
if (lastItemPosition == position)
return;
// imgSwitcher.setImageURI(Uri.fromFile(imgAdapter.imgFileList.get(position))); //太耗内存!改为以下几行:
ImageView image = (ImageView)imgSwitcher.getNextView();
image.setImageBitmap(imgAdapter.getImage(position));
//调整动画方式,可不要
if (lastItemPosition > position){
imgSwitcher.setInAnimation(slideInLeft);
imgSwitcher.setOutAnimation(slideOutRight);
}else{
imgSwitcher.setInAnimation(slideInRight);
imgSwitcher.setOutAnimation(slideOutLeft);
}
imgSwitcher.showNext();
//记录
lastItemPosition = position;
}