防止oom的通用适配器

一直以来加载图片oom都是android开发常见问题,很多加载图片也使用了类似imageloader这样的开源来做,但是如果没有合理使用照样会出oom情况。

那么一般在listview使用时候在下拉时候加载大量图片。

那么怎么才是合理使用?

应该要使用listview的回收原理来用是最合适的。

在下拉停止时候加载图片,不要使用多余图片加载,再配合缓存使用。

这里写一个适配器可以配合listview、gridview等来使用通用适配器。

代码:

public class NoOOMAdapter<T> extends BaseAdapter implements OnScrollListener {

	List<T> listinfo = new ArrayList<T>();
	List<Map<String, String>> listimg = new ArrayList<Map<String, String>>();
	Set<LoadTask> loadTasks = new HashSet<LoadTask>();
	ListView listView;
	Context context;
	int R_layout_id;
	LruCache<String, Bitmap> mCache;
	int firstVisible;
	int visibleNums;
	boolean isLoaded = true;
	LayoutInflater layoutInflater;

	public NoOOMAdapter(List<T> listinfo, List<Map<String, String>> arr,
			ListView listView, Context context, int r_layout_id) {
		super();
		this.listimg = arr;
		this.listinfo = listinfo;
		this.listView = listView;
		this.context = context;
		this.R_layout_id = r_layout_id;
		this.layoutInflater = LayoutInflater.from(context);
		// 初始化缓存函数
		int maxM = (int) Runtime.getRuntime().maxMemory();
		int cSize = maxM / 8;
		mCache = new LruCache<String, Bitmap>(cSize) {
			@Override
			protected int sizeOf(String key, Bitmap value) {
				// 获取全部字节数
				return value.getByteCount();
			}
		};
		// 绑定滑动监听
		listView.setOnScrollListener(this);
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return listinfo.size();
	}

	@Override
	public T getItem(int arg0) {
		// TODO Auto-generated method stub
		return (T)listinfo.get(arg0);
	}

	@Override
	public long getItemId(int arg0) {
		// TODO Auto-generated method stub
		return arg0;
	}

	@Override
	public View getView(int arg0, View arg1, ViewGroup arg2) {
		// TODO Auto-generated method stub
		ViewHolder viewHolder=new ViewHolder(context, arg2, R_layout_id, arg0);
		
		InitView(viewHolder, arg0);
		
		return viewHolder.getConvertView();
	}
	
	public void InitView(ViewHolder viewHolder,int pos){
		// 处理数据绑定逻辑
		
	}
	
	//获取数据集合
	public List<T> getListInfo() {
		return listinfo;
	}
	
	//获取图片集合
	public List<Map<String, String>> getImgList(){
		return listimg;
	}
	

	@Override
	public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		firstVisible = arg1;
		visibleNums = arg2;
		if (isLoaded && visibleNums > 0) {
			// 执行下载
			isLoaded = false;
			DownLoadAllTask(firstVisible, visibleNums);
		}
	}

	@Override
	public void onScrollStateChanged(AbsListView arg0, int arg1) {
		// TODO Auto-generated method stub
		if (arg1 == SCROLL_STATE_IDLE) {// 停止滑动
			DownLoadAllTask(firstVisible, visibleNums);
		} else {
			cancelAllTasks();
		}
	}

	// 清空缓存
	public void cancelAllTasks() {
		if (loadTasks != null) {
			for (LoadTask task : loadTasks) {
				task.cancel(false);// 取消下载任务
			}
		}
	}

	// 下载任务 有序加载
	class LoadTask extends AsyncTask<String, Void, Bitmap> {

		String imgurlString;// 图片地址
		int pos;//位置
		
		public LoadTask(int pos) {
			super();
			this.pos = pos;
		}

		@Override
		protected Bitmap doInBackground(String... arg0) {
			// TODO Auto-generated method stub
			imgurlString = arg0[0];
			Bitmap bitmap = downloadBitmap(imgurlString);
			if (bitmap != null) {
				// 下载完毕添加到缓存中
				addBitmapToMemoryCache(imgurlString, bitmap);
			}
			return bitmap;
		}

		@Override
		protected void onPostExecute(Bitmap result) {
			// TODO Auto-generated method stub
			super.onPostExecute(result);

			ImageView imageView = (ImageView) listView
					.findViewWithTag(imgurlString+"_"+pos);
			if (imageView != null && result != null) {
				imageView.setImageBitmap(result);
			}
			// 消灭自身任务
			loadTasks.remove(this);
		}

		// 图片下载
		Bitmap downloadBitmap(String imageUrl) {
			Bitmap bitmap = null;
			HttpURLConnection con = null;
			try {
				URL url = new URL(imageUrl);
				con = (HttpURLConnection) url.openConnection();
				con.setConnectTimeout(5 * 1000);
				con.setReadTimeout(10 * 1000);
				con.setDoInput(true);
				con.setDoOutput(true);
				bitmap = BitmapFactory.decodeStream(con.getInputStream());
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (con != null) {
					con.disconnect();
				}
			}
			return bitmap;
		}

	}

	static public class ViewHolder {
		private final SparseArray<View> mViews;
		private View mConvertView;

		private ViewHolder(Context context, ViewGroup parent, int layoutId,
				int position) {
			this.mViews = new SparseArray<View>();
			mConvertView = LayoutInflater.from(context).inflate(layoutId,
					parent, false);
			// setTag
			mConvertView.setTag(this);

		}
		
		public static ViewHolder get(Context context, View convertView,
				ViewGroup parent, int layoutId, int position) {

			if (convertView == null) {
				return new ViewHolder(context, parent, layoutId, position);
			}
			return (ViewHolder) convertView.getTag();
		}

		/**
		 * 通过控件的Id获取对于的控件,如果没有则加入views
		 * 
		 * @param viewId
		 * @return
		 */
		@SuppressWarnings("unchecked")
		public <T extends View> T getView(int viewId) {

			View view = mViews.get(viewId);
			if (view == null) {
				view = mConvertView.findViewById(viewId);
				mViews.put(viewId, view);
			}
			return (T) view;
		}

		public View getConvertView() {
			return mConvertView;
		}

	}

	// 添加缓存中
	public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
		if (getBitmapFromMemoryCache(key) == null) {
			mCache.put(key, bitmap);
		}
	}

	// 获取缓存
	public Bitmap getBitmapFromMemoryCache(String key) {
		return mCache.get(key);
	}

	// 开始任务
	void DownLoadAllTask(int firstV, int visibleN) {
		try {
			for (int i = firstV; i < (firstV + visibleN); i++) {
				if (i<listimg.size()) {
					Map<String, String> imgItem = listimg.get(i);
					// 迭代器
					Set<String> mKeys = imgItem.keySet();
					for (String string : mKeys) {
						String imgurlString = imgItem.get(string);
						Bitmap bitmap = getBitmapFromMemoryCache(imgurlString);
						if (bitmap == null) {
							LoadTask loadTask = new LoadTask(i);
							loadTask.execute(imgurlString);
							loadTasks.add(loadTask);
						} else {
							// 直接填充
							ImageView imageView = (ImageView) listView
									.findViewWithTag(imgurlString);
							if (imageView != null && bitmap != null) {
								imageView.setImageBitmap(bitmap);
							}
						}
					}
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

	// 设置图片
	protected void setImageView(String imageUrl, ImageView imageView, int imgId, int pos) {
		imageView.setImageResource(imgId);
		imageView.setTag(imageUrl+"_"+pos);
		Bitmap bitmap = getBitmapFromMemoryCache(imageUrl);
		if (bitmap != null) {
			imageView.setImageBitmap(bitmap);
		} else {
			imageView.setImageResource(imgId);// 如果没有内容为空图片
		}
	}

	// 工具函数 图片尺寸压缩函数
	public static int calculateInSampleSize(BitmapFactory.Options options,
			int reqWidth) {
		// 源图片的宽度
		final int width = options.outWidth;
		int inSampleSize = 1;
		if (width > reqWidth) {
			// 计算出实际宽度和目标宽度的比率
			final int widthRatio = Math.round((float) width / (float) reqWidth);
			inSampleSize = widthRatio;
		}
		return inSampleSize;
	}

	// 压缩图片质量
	public static Bitmap decodeSampledBitmapFromResource(String pathName,
			int reqWidth) {
		// 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
		final BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(pathName, options);
		// 调用上面定义的方法计算inSampleSize值
		options.inSampleSize = calculateInSampleSize(options, reqWidth);
		// 使用获取到的inSampleSize值再次解析图片
		options.inJustDecodeBounds = false;
		return BitmapFactory.decodeFile(pathName, options);
	}

}

有待完善


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值