[align=center][b][size=x-large]ListView异步加载网络图片完美版之双缓存技术[/size][/b][/align]
[size=large][b]问题描述:[/b]以前对ListView加载网络图片以及缓存机制进行了分析,本来自以为已经完美了,前段时间有朋友说还有问题,问题是[color=red]AsyncTask中的线程池满了>128[/color]。以前控制线程数量的方法是在ListView处于Fling状态的时候不去启动下载线程,然而这样的做法没有从更本上控制线程的数量。
[b]解决方案:[/b]今天我将通过生产者消费者模式+信号量来控制AsynTask的执行。
[/size]
[size=large][b]总结:[/b]我本来还想了一种解决的办法就是,在ViewHold中保留一个AsynTask的引用,如果AsyncTask的状态为Running则将其cancle,但是没有cancle掉,希望知道的朋友解答一下。[/size]
[size=large][b]问题描述:[/b]以前对ListView加载网络图片以及缓存机制进行了分析,本来自以为已经完美了,前段时间有朋友说还有问题,问题是[color=red]AsyncTask中的线程池满了>128[/color]。以前控制线程数量的方法是在ListView处于Fling状态的时候不去启动下载线程,然而这样的做法没有从更本上控制线程的数量。
[b]解决方案:[/b]今天我将通过生产者消费者模式+信号量来控制AsynTask的执行。
[/size]
// 通过信号量控制同时执行的线程数
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实际上会拿到刚刚缓存好的图片
}
[size=large][b]总结:[/b]我本来还想了一种解决的办法就是,在ViewHold中保留一个AsynTask的引用,如果AsyncTask的状态为Running则将其cancle,但是没有cancle掉,希望知道的朋友解答一下。[/size]