请注意,此问题的灵感来自对https://stackoverflow.com/a/33370816/519334的评论。
我有一个持有者类,它属于GridView项目,引用了ImageView
public static class Holder {
ImageView mRowImage;
String mImageUrl;
// neccessary to cancel unfinished download
BitmapLoaderAsyncTask mDownloader;
}
相应的GridItemAdapter使用AsyncTask获取GridItem的图像
public class GridItemAdapter extends BaseAdapter {
@Override
public View getView(int position, ...) {
...
if (view == null) {
holder = ...
...
} else {
holder = (Holder) view.getTag();
}
...
// cancel unfinished mDownloader
if (holder.mDownloader != null) {
holder.mDownloader.cancel(false);
holder.mDownloader = null;
}
holder.mImageUrl = mImageUrls.get(position);
holder.mDownloader = new BitmapLoaderAsyncTask()
holder.mDownloader.execute(holder);
}
}
static class BitmapLoaderAsyncTask extends AsyncTask<Holder, Void, Bitmap> {
Holder mHolder;
protected Bitmap doInBackground(Holder... holders) {
mHolder = holders[0];
...
}
protected void onPostExecute(...) {
mHolder.mDownloader = null;
if (!isCancelled()) {
this.mHolder.mRowImage.setImageBitmap(image);
}
this.mHolder = null;
}
}
注释表明在更改方向后,此代码可能存在问题。
SZENARIO
onPostExecute(..)
onPostExecute(..)
中,图片mHolder.mRowImage
已更新。由于mHolder.mRowImage
不再存在,因为方向发生变化所以应该会发生崩溃。我有code similar to the described scenario 直到现在我还没有(!!!)崩溃。
我的问题
onPostExecute(..)
mHolder.mRowImage
是否已无效?AsyncTask
?答案 0 :(得分:1)
由于mHolder.mRowImage不再存在,因为方向 改变所以应该发生崩溃。
这是不正确的,所有主题都是GC根源,而您的AsyncTask
强烈引用View
对象(它位于Holder
类内)和您的{ {1}}强烈引用Activity / Fragment / etc.因此,只要您的View
正在运行,您的Activity / Fragment / etc就不会被正确地进行垃圾回收。它不会导致任何崩溃(因为View确实存在),但会发生内存泄漏,结果将传递给旧的Activity / Fragment / etc。
但是,如果您确保AsyncTask
被正确取消,一切都会好的。但是,如果你想100%确定你应该使用AsyncTask
在[{1}}
WeakReference
课程
@edit
现在取消任务的方式不正确。在方向改变之后,所有视图将再次膨胀(在新的Activity / Fragment / etc中),因此view.getTag将始终为null。