在编写多图片上传时,遇到一个很郁闷的问题,就是在gridview中添加一个“+”项,经常会被后面添加的图片覆盖,变成两个图片一模一样。后面才发现,Gridview的Adapter会重复使用item项目来提高效率,这样当重新刷新时,每个item会被重新使用,但一次刷新时,一个position会一直使用一个item。
由于这个特性,当异步加载图片时,异步加载的图片还未完成,这样一个相同的item可能就会出现不是你想要的图片(原因就是你的item换成一个新的图片,而这个换的动作比上次用这个item去异步加载图片的快,因此即使这次换成功了,也会被异步加载成功的图片替换)。
简单说:就是一个item换两次图片时,哪个加载快就会被加载慢的图片覆盖。
那如何解决呢?
很简单,每个换图片时,将图片的路径设置在item的tag上,每次真正换图片时(调用setImageBitmap),判断此时的tag值和你换的最新图片的path是否一致,一致时才替换。
加上代码:
public class BitmapCache {
public static void display(final ImageView iv,
final String thumbPath,
final String sourcePath,
final int reqWidth,
final int reqHeight) {
if (TextUtils.isEmpty(thumbPath) && TextUtils.isEmpty(sourcePath)) {
return;
}
final String path;
if (!TextUtils.isEmpty(thumbPath)) {
path = thumbPath;
} else if (!TextUtils.isEmpty(sourcePath)) {
path = sourcePath;
} else {
return;
}
if (iv.getTag() != null
&& iv.getTag().toString().equals(path)) {
return;
}
iv.setTag(path);
Bitmap bitmap = GlobalContext.getInstance().getBitmapCache().get(path + reqWidth + reqHeight);
if (bitmap != null) {
iv.setImageBitmap(bitmap);
return;
}
iv.setImageBitmap(null);
new MyAsyncTask<Void, Bitmap, Bitmap>() {
//todo
//when I finish new ImageView in the future, I will refactor these code....
@Override
protected Bitmap doInBackground(Void... params) {
Bitmap bitmap = null;
try {
bitmap = ImageUtility
.decodeBitmapFromSDCard(path, reqWidth, reqHeight);
} catch (OutOfMemoryError ignored) {
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if (bitmap != null) {
// 判断 tag是否和最新的路径一致
if (path.equals(iv.getTag())) {
iv.setImageBitmap(bitmap);
}
GlobalContext.getInstance().getBitmapCache().put(path + reqWidth + reqHeight, bitmap);
}
}
}.executeOnExecutor(MyAsyncTask.THREAD_POOL_EXECUTOR);
}
}
重点在这:
if (iv.getTag() != null
&& iv.getTag().toString().equals(path)) {
return;
}
iv.setTag(path);
和这:
if (path.equals(iv.getTag())) {
iv.setImageBitmap(bitmap);
}