我有很多图像的gridview,我可以在这个gridview中显示不同的图像组,可以通过按下某些按钮来改变它们。为了防止使用大量内存,我会在更改图像组后回收所有下载的图像。这样的事情:
我的适配器为视图加载图像,并将它们传输到视图中。更改图像组后,我正在调用方法recycleImages()来回收所有已保存的图像
public class DataArrayAdapter<T extends View & DataListViewItem> extends ArrayAdapter<DataObject>
{
//Loaded images. Key - position, value - image
private SparseArray<Drawable> mImages;
@Override
public View getView(int position, View convertView, ViewGroup parent) {
T view = (T) convertView;
if (view == null) {
view = createView(position);
} else {
//reuse view by transfering new data to it
view.updateListViewItem(getItem(position));
}
checkViewImage(view, position);
return view;
}
protected void checkViewImage(T view, int position) {
if (view.needImage()) {
if (mImages == null) {
mImages = new SparseArray<Drawable>();
}
Drawable image = mImages.get(position);
if (image == null) {
String imageUrl = getItem(position).getUrl();
if (imageUrl != null) {
//download image and put it to view after download
ImageRequest imageRequest = new ImageRequest(imageUrl, view);
imageRequest.send();
}
} else {
view.setImageDrawable(image);
}
}
}
public void recycleImages() {
if (mImages != null) {
Drawable drawable;
for (int i = 0, l = mImages.size(); i < l; ++i) {
drawable = mImages.valueAt(i);
if (drawable instanceof BitmapDrawable) {
((BitmapDrawable) drawable).getBitmap().recycle();
}
}
mImages.clear();
}
}
}
问题是我重复使用视图并在回收图像后出现错误:
java.lang.IllegalArgumentException:无法绘制回收的位图
因为旧图像被回收但新图像尚未下载。
在回收drawables后,我为每个使用过的imageView调用了setImageDrawable(null),但它没有帮助。
一个很奇怪的是,这个错误不会在Android 4.0.4的平板电脑上重现,但它会在4.3及更高版本上重现
我该如何解决这个问题?
修改
ImageRequest是简单的AsyncTask,它在onPostExecute方法中创建ViewHolder类的对象并将其保存在List中。所有这些类都在DataArrayAdapter
protected void onPostExecute(Drawable image) {
mHolders.add(new ViewHolder(mView, image));
checkLoaders();
}
private class ViewHolder {
private T mView;
private Drawable mImage;
public ViewHolder(T view, Drawable image) {
mView = view;
mImage = image;
}
public void combine() {
if (mView != null) {
mView.setImageDrawable(mImage);
mView = null;
mImage = null;
}
}
}
在加载所有图像后,方法组合被调用到所有创建的ViewHolder对象,以便在一瞬间绘制所有图像