照片墙的实现原理

首先,这篇文章参照大神的文章,这里只是相当于自己的学习笔记吧。原文:点击打开链接

首先,在很多时候,当我们在使用GridView加载的时候,我们需要加载很多的item,其中每个Item都可能包含有图片。图片加载多了就容易OOM。所以,利用LruCache来避免OOM是一种不错的方法。它使得内存中的图片始终维持在一个固定的水平。。。以下是代码的实现过程。

这里中涉及到的几个重点:

第一是LruCache。这是官方API:

A cache that holds strong references to a limited number of values. Each time a value is accessed, it is moved to the head of a queue. When a value is added to a full cache, the value at the end of that queue is evicted and may become eligible for garbage collection.

一个包含了一定数目值的强引用的缓冲区。每次当一个值到达的时候,它移到队列的最前面。当队列满的时候,值到达,队列最后面的值将可能会被垃圾回收。。。。

public class PhoneWallAdapter extends ArrayAdapter<String> implements OnScrollListener {
	
	//第一个可见的下标	
	int firstVisibleItem;
	//一屏加载的数目,实现当图片数目多于屏幕可加载的数量时,多余的暂时不加载
	int visibleItemCount;
	//用于缓存图片的内存大小
	int mMemoryCache;
	//存放下载任务的集合
	HashSet<DownLoadTask> taskSet;
	//一个存放图片引用的队列。。。当队列中缓冲区满时,队尾的引用会被自动回收。。。。
	LruCache<String,Bitmap>mLruCache;
	
	Context context;
	GridView gridView;
	boolean isFirstEnter=true;
	String []path;
	public PhoneWallAdapter(Context context, int textViewResourceId,String[]path,GridView gridView) {
		super(context, textViewResourceId);
		this.context=context;
		this.gridView=gridView;
		this.path=path;
		taskSet=new HashSet<DownLoadTask>();
		mMemoryCache=(int)Runtime.getRuntime().maxMemory()/8;
		mLruCache=new LruCache<String,Bitmap>(mMemoryCache){

			@Override
			protected int sizeOf(String key, Bitmap bitmap) {
				return bitmap.getByteCount();
			}
			
		};
		this.gridView.setOnScrollListener(this);
	}


	@Override
	public int getCount() {
		return path.length;
	}


	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		View view;
		String url=path[position];
		if(convertView==null)
		{
			LayoutInflater inflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			view=inflater.inflate(R.layout.image, null);
		}
		else
		{
			view=convertView;
		}
		ImageView iv=(ImageView) view.findViewById(R.id.image);
		//给ImageView添加标记。这样就可以通过tag来定位了。
		iv.setTag(url);
		setImageView(url,iv);
		return view;
	}
	
	private void setImageView(String url, ImageView iv) {
		//从缓冲区中加载图片,没有的话就设置为默认的图片
		Bitmap mBitmap=getBitmapFromCache(url);
		if(mBitmap==null)
		{
			iv.setImageResource(R.drawable.empty_photo);
			
		}
		else
		{
			iv.setImageBitmap(mBitmap);
		}
	}

	private void addBitmapToCache(String url,Bitmap mBitmap)
	{
		//将图片加载到缓冲区中
		if(getBitmapFromCache(url)==null)
		{
			mLruCache.put(url, mBitmap);
		}
	}
	
	private Bitmap getBitmapFromCache(String url)
	{
		return mLruCache.get(url);
	}

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		//不滑动的时候加载
		if(scrollState==SCROLL_STATE_IDLE)
		{
			loadBitmaps(firstVisibleItem,visibleItemCount);
		}else
		{//滑动的时候取消下载
			cancelAllTask();
		}
		
	}

	private void loadBitmaps(int firstVisibleItem, int visibleItemCount) {
		for(int i=firstVisibleItem;i<firstVisibleItem+visibleItemCount;i++)
		{
			String tag=Images.imageThumbUrls[i];
			Bitmap mBitmap=mLruCache.get(tag);
			if(mBitmap==null)
			{
				DownLoadTask loadTask=new DownLoadTask();
				//将下载任务加入到集合中,下载完成后可以从集合中删除。
				taskSet.add(loadTask);
				loadTask.execute(tag);
				
			}else
			{
				ImageView iv=(ImageView) gridView.findViewWithTag(tag);
				iv.setImageBitmap(mBitmap);
			}
		}
		
	}


	//在这里也许会迷糊,为什么在onScroll里面调用呢?看API。
	@Override
	public void onScroll(AbsListView view, int firstVisibleItem,
		int visibleItemCount, int totalItemCount) {
		this.visibleItemCount=visibleItemCount;
		this.firstVisibleItem=firstVisibleItem;
		if(isFirstEnter==true&&visibleItemCount>0)
		{
			loadBitmaps(firstVisibleItem,visibleItemCount);
			isFirstEnter=false;
			
		}
	}
	public void cancelAllTask()
	{
		for(DownLoadTask task:taskSet)
		{
			task.cancel(false);
		}
		
	}
	
	public Bitmap downloadBitmap(String s)
	{
		InputStream is=null;
		try
		{
			URL url=new URL(s);
			HttpURLConnection conn=(HttpURLConnection) url.openConnection();
			is=conn.getInputStream();
			Bitmap mBitmap=BitmapFactory.decodeStream(is);
			return mBitmap;
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		finally
		{
			if(is!=null)
			{
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}
	
	class DownLoadTask extends AsyncTask<String,Void,Bitmap>
	{

		private Bitmap mBitmap;
		private String tag;
		@Override
		protected Bitmap doInBackground(String... params) {
			try {
				tag=params[0];
				mBitmap = downloadBitmap(tag);
				//将下载好的图片加入到LruCache对象中
				addBitmapToCache(params[0], mBitmap);
				//图片下载完成后,将该图片的下载任务从集合中删除。
				taskSet.remove(this);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return mBitmap;
		}

		@Override
		protected void onPostExecute(Bitmap result) {
			//通过tag来定位imageView
			ImageView view=(ImageView) gridView.findViewWithTag(tag);
			if(view!=null&&result!=null)
			{
				view.setImageBitmap(result);

			}
		}

	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值