Chu*_*ger 13 java android android-fragments
关于如何在AsyncTask期间处理配置更改的帖子很多,但是当AsyncTask完成并尝试解除DialogFragment(兼容性库)时,我找不到任何关于后台应用程序(onPause())的明确解决方案.
这是问题,如果我有一个AsyncTask运行应该解雇onPostExecute()中的DialogFragment,如果应用程序在后台尝试关闭DialogFragment时,我会收到IllegalStateException.
private static class SomeTask extends AsyncTask<Void, Void, Boolean> {
public SomeTask(SomeActivity tActivity)
{
mActivity = tActivity;
}
private SomeActivity mActivity;
/** Set the view during/after config change */
public void setView(Activity tActivity) {
mActivity tActivity;
}
@Override
protected Boolean doInBackground(Void... tParams) {
try {
//simulate some time consuming process
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException ignore) {}
return true;
}
@Override
protected void onPostExecute(Boolean tRouteFound) {
mActivity.dismissSomeDialog();
}
}
Run Code Online (Sandbox Code Playgroud)
活动看起来像这样:
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
public class SomeActivity extends FragmentActivity {
public void someMethod() {
...
displaySomeDialog();
new SomeTask(this).execute();
...
}
public void displaySomeDialog() {
DialogFragment someDialog = new SomeDialogFragment();
someDialog.show(getFragmentManager(), "dialog");
}
public void dismissSomeDialog() {
SomeDialogFragment someDialog = (SomeDialogFragment) getFragmentManager().findFragmentByTag("dialog");
someDialog.dismiss();
}
....
}
Run Code Online (Sandbox Code Playgroud)
工作正常,除非SomeTask仍在运行,应用程序切换到后台.在这种情况下,当SomeTask尝试dismissSomeDialog()时,我得到一个IllegalStateException.
05-25 16:36:02.237: E/AndroidRuntime(965): java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
Run Code Online (Sandbox Code Playgroud)
我所看到的所有帖子似乎都指向了一些复杂的方向,并提供了精心设计的解决方法.是不是有一些android处理方式?如果它是Dialog而不是DialogFragment,那么Activity的dismissDialog()会正确处理它.如果它是一个真正的DialogFragment而不是ACP中的一个,那么dismissAllowingStateLoss()会处理它.对于ACP版本的DialogFragment,是不是有这样的东西?
Ale*_*ood 22
片段被保存为每个Activity状态的一部分,因此在onSaveInstanceState()技术上调用之后执行事务是没有意义的.
commitAllowingStateLoss()在这种情况下,您绝对不想使用以避免异常.以此场景为例:
AsyncTask.该AsyncTask节目一DialogFragment中onPreExecute(),并开始在后台线程执行其任务.Activity停止并强制进入后台.系统决定该设备的内存非常低,因此它决定它也应该销毁它Activity.AsyncTask完成和onPostExecute()被调用.在onPostExecute()你内部解雇DialogFragment使用commitAllowingStateLoss()以避免异常.Activity.在FragmentManager将根据恢复其片段的状态Activity保存状态的.被保存的状态在onSaveInstanceState()被调用之后不知道任何事情,所以即使已经完成,DialogFragment也不会记住解雇该请求的请求并且DialogFragment将恢复AsyncTask.由于偶尔会发生类似这些奇怪的错误,因此使用它commitAllowingStateLoss()来避免此异常通常不是一个好主意.因为AsyncTask回调方法(响应后台线程完成其工作Activity而调用)与生命周期方法完全无关(系统服务器进程响应系统范围的外部事件调用,例如设备掉落睡着了,或内存不足),处理这些情况需要你做一些额外的工作.当然,这些错误是非常罕见的,保护您的应用程序不受它们的影响通常不是1星评级和游戏商店的5星评级之间的差异......但它仍然需要注意.
希望这至少有一定意义.另外,请注意Dialogs也作为Activitys状态的一部分存在,所以尽管使用普通旧的Dialog可能会避免异常,但你基本上会遇到同样的问题(即,Dialog当Activity稍后恢复状态时,不会记住这个问题) .
坦率地说,最好的解决方案是避免在整个过程中显示对话AsyncTask.一个更加用户友好的解决方案是显示一个不确定的进度微调器ActionBar(例如G +和Gmail应用程序).导致用户界面发生重大变化以响应异步回调对用户体验不利,因为它是意外的并且突然使用户不再正在做他们正在做的事情.
Zac*_*sky 16
要解决非法状态异常问题并基本上实现dismissAllowingStateLoss()可以使用以下方法完成.
getFragmentManager().beginTransaction().remove(someDialog).commitAllowingStateLoss();
Run Code Online (Sandbox Code Playgroud)
这应该在没有hacky代码的情况下解决问题.如果线程使用dialog.show()通过处理程序与UI线程进行通信,则也可以应用于show.这也可能导致非法状态异常
getFragmentManager().beginTransaction().add(someDialog).commitAllowingStateLoss();
Run Code Online (Sandbox Code Playgroud)
getFragmentManager()
Run Code Online (Sandbox Code Playgroud)
同
getSupportFragmentManager()
Run Code Online (Sandbox Code Playgroud)
Activity应假定异步任务可能无法完成,并且它不会执行onPostExecute().无论UI动作(即,微调器,理想情况下不是对话框)开始通知用户异步操作,都应该有超时或跟踪状态自动停止并检查onRestore/onResume类型生命周期事件以确保UI已正确更新.服务也可能值得调查.
| 归档时间: |
|
| 查看次数: |
17390 次 |
| 最近记录: |