同方向变化后未完成的AsyncTask视图引用会发生什么? [英] What happens with view references in unfinished AsyncTask after orientation change?
问题描述
请注意这个问题是由以 http://stackoverflow.com/a/33370816/519334 评论启发。
我有属于与参考的GridView项到ImageView的一个holder类
公共静态类持有人{
ImageView的mRowImage;
串mImageUrl; // neccessary取消未完成的下载
BitmapLoaderAsyncTask mDownloader;
}
相应GridItemAdapter使用一个的AsyncTask获取图像的的GridItem
公共类GridItemAdapter延伸BaseAdapter {
@覆盖
公共查看getView(INT位置,...){
...
如果(查看== NULL){
持有人= ...
...
}其他{
支架=(座)view.getTag();
}
...
//取消未完成的mDownloader
如果(holder.mDownloader!= NULL){
holder.mDownloader.cancel(假);
holder.mDownloader = NULL;
}
holder.mImageUrl = mImageUrls.get(位置);
holder.mDownloader =新BitmapLoaderAsyncTask()
holder.mDownloader.execute(保持器);
}
}静态类BitmapLoaderAsyncTask扩展的AsyncTask<支架,太虚,位图> {
持有人mHolder;
保护位图doInBackground(持有人持有...){
mHolder =持有者[0];
...
}
保护无效onPostExecute(...){
mHolder.mDownloader = NULL;
如果(!isCancelled()){
this.mHolder.mRowImage.setImageBitmap(图片);
}
this.mHolder = NULL;
}
}
注释建议,有可能与方向改变后,这个code的一个问题。
SZENARIO
- 电网是在风景 - 模式
- GridItemAdapter开始BitmapLoaderAsyncTask#1装载Image1.jpg
- 异步任务有mHolder.mRowImage
- 从横向网格方向更改为纵向模式
- BitmapLoaderAsyncTask#1结束,并呼吁
onPostExecute(..)
- (!)在
onPostExecute(..)
mHolder.mRowImage
更新的形象。自mHolder.mRowImage
不存在了,因为方向的改变所以应该有一个崩溃。
我有<一个href=\"https://github.com/k3b/AndroFotoFinder/blob/FDroid/app/src/main/java/de/k3b/android/androFotoFinder/gallery/cursor/GalleryCursorAdapter.java\"的rel =nofollow的> code类似描述的场景
而到现在为止我HAVN-T有(!)崩溃呢。
我的问题
- 这是刚刚coincedence,有没有(!)崩溃了吗?
- 有一个简单的解决方案,在
onPostExecute(..)
的mHolder.mRowImage
是无效的检查更多? - 或者是有什么在Android中,保护
的AsyncTask
由于mHolder.mRowImage不存在了,因为方向
改变所以应该有一个崩溃。
块引用>这是不正确的,所有的线程都GC根,你的
的AsyncTask
持有强引用查看
对象(这是你的架
类中),你的查看
具有较强的参考活动/片段/等。所以,你的活动/片段/等不能得到妥善的垃圾,只要收集你的的AsyncTask
正在运行。它不会造成任何崩溃(因为做观存在),但内存泄漏会发生和结果将被传递到老年活动/片段/等。然而,如果你确保
的AsyncTask
取消妥善一切都会好的。但是,如果你想成为100%肯定,你应该使用的WeakReference
来抱你在持有人
类BitmapLoaderAsyncTask
@edit
你现在的任务取消的方式不正确。取向后改变所有的视图将被再次充气(新活动/片段/等),从而view.getTag总是会导致空。
Note this question was inspired by a comment to http://stackoverflow.com/a/33370816/519334 .
I have a holder class that belongs to a GridView-item with a reference to an ImageView
public static class Holder { ImageView mRowImage; String mImageUrl; // neccessary to cancel unfinished download BitmapLoaderAsyncTask mDownloader; }
The corresponding GridItemAdapter uses an AsyncTask to get the image for the 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; } }
A comment suggested that there might be a problem with this code after orientation change.
Szenario
- Grid is in Landscape - mode
- GridItemAdapter starts BitmapLoaderAsyncTask#1 for loading Image1.jpg
- async task has mHolder.mRowImage
- Grid orientation changes from Landscape to Portrait mode
- BitmapLoaderAsyncTask#1 finishes and calls
onPostExecute(..)
- (!!!) In
onPostExecute(..)
the imagemHolder.mRowImage
is updated. SincemHolder.mRowImage
does not exist any more because orientation change so there should be a crash.I have code similar to the described scenario and up to now I havn-t had the (!!!) crash yet.
My Question
- Is this just coincedence that there was no (!!!) crash yet?
- Is there a simple solution to check in
onPostExecute(..)
thatmHolder.mRowImage
is not valid any more?- Or is there something in Android that protects the
AsyncTask
?解决方案Since mHolder.mRowImage does not exist any more because orientation change so there should be a crash.
That is not correct, all Threads are GC roots, and your
AsyncTask
is holding strong reference toView
object (it's inside yourHolder
class) and yourView
has strong reference to Activity/Fragment/etc. So your Activity/Fragment/etc won't be properly garbage collected as long as yourAsyncTask
is running. It won't cause any crash (because View do exists) but memory leak will occur and result will be delivered to old Activity/Fragment/etc.However if you make sure that
AsyncTask
is cancelled properly everything will be ok. But if you want to be 100% sure you should useWeakReference
to hold youHolder
class inBitmapLoaderAsyncTask
@edit
The way you do task cancelling now is incorrect. After orientation change all the view will be inflated once again (in new Activity/Fragment/etc), thus view.getTag will always result null.
这篇关于同方向变化后未完成的AsyncTask视图引用会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!