ListView异步加载网络图片完美版之双缓存技术(续)

ListView异步加载网络图片完美版之双缓存技术

问题描述:以前对ListView加载网络图片以及缓存机制进行了分析,本来自以为已经完美了,前段时间有朋友说还有问题,问题是AsyncTask中的线程池满了>128。以前控制线程数量的方法是在ListView处于Fling状态的时候不去启动下载线程,然而这样的做法没有从更本上控制线程的数量。
解决方案:今天我将通过生产者消费者模式+信号量来控制AsynTask的执行。

// 通过信号量控制同时执行的线程数
	Semaphore mSemaphore = new Semaphore(50);

	// 这里是任务的消费者,去任务队列取出下载任务,然后执行,当没有任务的时候消费者就等待
	class Executor extends Thread {
		@Override
		public void run() {
			while (true) {
				ImageLoadTask task = null;
				try {
					task = mTasks.take();
					if (task != null) {
						mSemaphore.acquire();
						task.execute();
						task.cancel(true);
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

public void loadImage(String url, BaseAdapter adapter, ViewHolder holder) {
		resetPurgeTimer();
		Bitmap bitmap = getBitmapFromCache(url);// 从缓存中读取
		if (bitmap == null) {
			holder.mImageView.setImageResource(R.drawable.ic_launcher);// 缓存没有设为默认图片
			ImageLoadTask imageLoadTask = new ImageLoadTask(url, adapter);
			try {
				//将任务放入队列中
				mTasks.put(imageLoadTask);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} else {
			holder.mImageView.setImageBitmap(bitmap);// 设为缓存图片
		}
	}


@Override
		protected void onPostExecute(Bitmap result) {
			mSemaphore.release();
			if (result == null) {
				return;
			}
			addImage2Cache(url, result);// 放入缓存
			adapter.notifyDataSetChanged();// 触发getView方法执行,这个时候getView实际上会拿到刚刚缓存好的图片
		}


总结:我本来还想了一种解决的办法就是,在ViewHold中保留一个AsynTask的引用,如果AsyncTask的状态为Running则将其cancle,但是没有cancle掉,希望知道的朋友解答一下。

猜你喜欢

转载自heisedeyueya.iteye.com/blog/1757010