Android ImageSwitcher 和 Gallery 浏览图片时 OutofMemory问题的解决


网上有很多例子介绍 ImageSwitcher 和 Gallery 配合浏览图片(其实看起来都是从一个来源拷贝的),大部分都有两个问题:

1、只讲了如何浏览应用内置资源,而没有给出浏览SD卡上图片的方法;

2、没有提到实际应用中会碰到的问题,就是内存不足的异常。


其中第一个问题有少数例子提到了解决方法,而第二个问题迄今为止尚未看到有人讨论。本人参考了一些资料,找到一种解决方法如下:


  1. 首先让自定义的ImageAdapter保存一个图片目录路径,用File.listFiles() 方法列出所有图片文件(根据需要,可能要排除一些非图片文件);
  2. 在需要时用 BitmapFactory.decodeFile() 解码出图片 的位图,在ImageAdapter 的  getView方法中,用ImageView.setImageBitmap()方法指定图片的位图;
  3. 将解码出的图片Bitmap用SoftReference保存,作为缓存,并便于系统需要内存时能够自动释放;
  4. 在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;
		
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值