我很欣赏关于 AsyncTask 轮换更改的大量帖子。使用兼容性库并尝试在 onPostExecute
中关闭 DialogFragment
时,我遇到以下问题。
我有一个触发 AsyncTask 的片段,该片段显示进度 DialogFragment
,然后在 onPostExecute
中关闭对话框,然后可能抛出另一个 DialogFragment
。
如果显示进度对话框时我将应用程序置于后台,我的片段将得到以下信息:
1) onPause
2) onSaveInstanceState
3) onPostExecute< /code> 我尝试在其中关闭并调用一个对话框。
我收到一个 IllegalStateException
,因为我试图在活动保存其状态时有效地提交事务,并且我理解这一点。
在轮换中,我假设(可能是错误的)在重新创建活动之前我不会得到 onPostExecute
。但是,当将应用程序放入后台时,我假设(绝对错误)在片段/活动暂停时不会调用 onPostExectute
。
我的问题是,我的解决方案是否只是在 onPostExecute
中检测片段/活动已暂停,然后简单地在 onResume
中执行我需要执行的操作?我觉得有点丑。
预先感谢,彼得。
编辑1
需要支持2.1及以上
编辑2
我考虑过使用FragmentTransaction:add
和FragmentTransaction:commitAllowingStateLoss
显示对话框代码>但这并非没有问题。
I appreciate the numerous postings regarding AsyncTask on a rotation change. I have the following problem when using the compatability lib and trying to dismiss a DialogFragment
in onPostExecute
.
I have a fragment which fires of an AsyncTask which displays a progress DialogFragment
, then in onPostExecute
dismisses the dialog and then potentially throws up another DialogFragment
.
If when the progress dialog is being displayed I put the application into the background I get the following for my fragment:
1) onPause
2) onSaveInstanceState
3) onPostExecute
in which I try to dismiss and invoke a dialog.
I get an IllegalStateException
because I'm trying to effectively commit a transaction when the activity has saved its state and I understand this.
On a rotation I've assumed (perhaps incorrectly) that I wouldn't get an onPostExecute
until the activity has been recreated. However, when putting the application into the background I assumed (definitely incorrectly) that the onPostExectute
wouldn't get called while the fragment/activity was paused.
My question is, is my solution to simply detect in onPostExecute
that the fragment/activity is paused and simply perform what I need to do in onResume
instead? Seems somewhat ugly to me.
Thanks in advance, peter.
Edit 1
Need to support 2.1 and above
Edit 2
I have considered showing the dialog using FragmentTransaction:add
and FragmentTransaction:commitAllowingStateLoss
however this isn't without its problems.
发布评论
评论(5)
我想出了一个解决这个问题的方法,没有任何重大的解决方法:
如何维护进度对话框和异步任务的基本思想在此 blogentry (当然我使用的是AsyncTaskComplex版本)。所有的功劳都归于这篇博文的作者,我只添加了一件小事:
显然我不再使用 showDialog() 了。相反,我坚持使用 DialogFragments。
第二个调整是重要的,它还解决了 IllegalStateException 的问题:我
不仅在 onRetainCustomNonConfigurationInstance() 中告诉异步任务没有更多活动,而且还在 onPause() 中执行此操作。我不仅在 onCreate() 中告诉 asynctask 有一个新活动,而且还在 onResume() 中执行此操作。
就这样,当 Activity 不可见时,您的 AsyncTask 不会尝试通知您的 Activity 其完成情况,从而导致 IllegalStateException。
如果您想查看更多代码而不是文字,请发表评论。
/编辑:
展示我的解决方案的源代码,我认为这是一个相当不错的解决方案:)
}
I came up with a solution for this problem without any major workaround:
The basic idea how to maintain a progressdialog and a asynctask is described in this blogentry (of course I used the AsyncTaskComplex-Version). All credits go to the author of this blogentry, I only added a tiny thing:
Obviously I'm not using showDialog() anymore. Instead I stick with DialogFragments.
The second tweak is the importent one and also solves the problem with the IllegalStateException:
Instead of only telling the asynctask in onRetainCustomNonConfigurationInstance() that there is no more activity I also do it in onPause(). And instead of only telling the asynctask in onCreate() that there is a new activity I also do it in onResume().
And there you go, your AsyncTask will not try to inform your activity about his finish causing an IllegalStateException when the activity is not visible.
If you would like to see more code instead of words, leave a comment.
/edit:
Sourcecode to show my solution, which I think is a pretty decent one :)
}
关于如何在活动/片段暂停时处理处理程序消息 我提供了另一种使用 BroadcastReceiver 的方法。
我认为它更干净、更优雅,它提供的优点是您可以从应用程序中的任何位置调用基本片段上的代码,并且通过使用粘性广播,您的调用可以在片段恢复后“记住”并执行。
On How to handle Handler messages when activity/fragment is paused I offer another approach using a BroadcastReceiver.
I consider it cleaner more elegant and it offers the advantages that you can invoke code on your base fragment from everywhere within your app and by using sticky broadcasts your invocation can be "remembered" and executed after your fragment resumes.
如果您需要将任务与活动生命周期同步,我相信 Loaders 正是您所需要的。更具体地说,您应该使用 AsyncTaskLoader 来完成这项工作。因此,现在您无需运行 AsyncTask,而是启动加载程序,然后等待侦听器中的响应。如果活动暂停,您将不会收到回调,这部分将为您管理。
还有另一种方法可以处理此任务:使用 保留其实例。总体思路是创建一个没有 UI 的片段并调用
setRetainInstance(true)
。它有一个任务,正在通知活动是否可用。如果没有,任务的线程将挂起,直到有活动可用。If you need to synchronize your task with the activity lifecycle, I believe that Loaders are exactly what you need. More specifically, you should use AsyncTaskLoader to do the job. So now instead of running an AsyncTask, you launch your loader, then wait for response in a listener. If the activity is paused, you won't get a callback, this part will be managed for you.
There is another way to handle this task: using a fragment which retains its instance. The general idea is that you create a fragment without UI and call
setRetainInstance(true)
. It has a task which is being notified about the activity being available or not. If not, the task's thread suspends until an activity becomes available.实现您所需的另一种方法是实现我在这篇文章中记录的 PauseHandler 类。
然后在 onPostExecute 方法中调用 sendMessage() 将消息发布到处理程序中。
当您的应用程序恢复时,将处理该操作。
Another way of achieving what you require is to implement the PauseHandler class that I documented in this post.
Then in your onPostExecute method call sendMessage() to post your message into the handler.
When your application resumes the action will be handled.
我更喜欢使用 guava、otto 或 eventbus 等总线库,而不是使用 BroadcastReceiver。它们的性能比广播接收器实现要好得多。
Rather then using BroadcastReceiver, I prefer using bus libraries like guava, otto or eventbus. Their performance is much better then the broadcast receiver implementation.