AsyncTask 在另一个线程中运行复杂任务是一件好事.
但是当AsyncTask仍在运行时有方向更改或其他配置更改时,将Activity消除并重新启动电流.并且当实例AsyncTask连接到该活动时,它会失败并导致"强制关闭"消息窗口.
所以,我正在寻找某种"最佳实践"来避免这些错误并防止AsyncTask失败.
到目前为止我看到的是:
onRetainNonConfigurationInstanceActivity并Activity在再次创建时重新启动它.一些代码示例:
屏幕旋转期间的Android AsyncTasks,第一部分和第二部分
你能帮我找到最好的方法来解决问题并且易于实现吗?代码本身也很重要,因为我不知道如何正确解决这个问题.
我很欣赏有关轮换更改的AsyncTask的大量帖子.使用兼容性lib并试图解雇DialogFragmentin 时,我有以下问题onPostExecute.
我有一个片段,它触发AsyncTask显示进度DialogFragment,然后onPostExecute解散对话框然后可能抛出另一个DialogFragment.
如果在显示进度对话框时我把应用程序放到后台我得到了以下片段:
1) onPause
2) onSaveInstanceState
3)onPostExecute我尝试解雇并调用对话框.
我得到一个IllegalStateException因为我正在尝试在活动保存状态时有效地提交事务并且我理解这一点.
在轮换中,我假设(可能不正确)onPostExecute在重新创建活动之前我不会得到.但是,当把应用程序放到后台时,我假设(肯定是错误的)onPostExectute在片段/活动暂停时不会被调用.
我的问题是,我的解决方案是简单地检测onPostExecute到片段/活动暂停并简单地执行我需要做的事情onResume吗?对我来说似乎有些难看.
提前谢谢,彼得.
编辑1
需要支持2.1及以上版本
编辑2
我已经考虑过使用对话框FragmentTransaction:add,FragmentTransaction:commitAllowingStateLoss但这并非没有问题.
android android-lifecycle android-asynctask android-fragments
我正在做一些后台工作并在我这样做时显示DialogFragment.完成我的工作并调用相关的回调后,我将关闭该对话框.当我这样做时,我在Android源代码中遇到了由NPE引起的崩溃,这里:
void dismissInternal(boolean allowStateLoss) {
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
mRemoved = true;
if (mBackStackId >= 0) {
getFragmentManager().popBackStack(mBackStackId,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
mBackStackId = -1;
} else {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.remove(this);
if (allowStateLoss) {
ft.commitAllowingStateLoss();
} else {
ft.commit();
}
}
}
Run Code Online (Sandbox Code Playgroud)
特别是在线: FragmentTransaction ft = getFragmentManager().beginTransaction();
为了清楚起见,我已经阅读了关于"IllegalStateException:在onSaveInstanceState之后无法执行此操作"的十几个SO问题,我已经阅读了Alex Lockwood的博客文章http://www.androiddesignpatterns.com/2013/08/片段事务提交状态-loss.html
所以我不是盲目地问这个.
我有一个非常简单的用例案例,不涉及AsyncTask或任何后台处理.
我有一个包含按钮的片段.在按钮的onClickListener上,我创建了一个DialogFragment并显示它.
public final class OverviewFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.overview_fragment, container, false);
startNewGameButton = (Button) view.findViewById(R.id.buttonNewGame);
startNewGameButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final NewGameFragment dialogFrag = NewGameFragment.create(getApplication());
dialogFrag.show(getFragmentManager(), NewGameFragment.FRAGMENT_TAG);
}
});
}
Run Code Online (Sandbox Code Playgroud)
[NewGameFragment]
public final class NewGameFragment extends DialogFragment {
public static final String FRAGMENT_TAG = "NewGameFragment";
private static final String MESSAGE = "message";
public static NewGameFragment …Run Code Online (Sandbox Code Playgroud) android android-lifecycle android-fragments android-dialogfragment android-nested-fragment
Fragments API发布后,我开始使用兼容包将所有已弃用的对话框移植到DialogFraments中.一切都运行良好,直到我注意到我的对话框仅导致ICS崩溃:
E/AndroidRuntime( 883): FATAL EXCEPTION: main
E/AndroidRuntime( 883): java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
E/AndroidRuntime( 883): at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1254)
E/AndroidRuntime( 883): at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1265)
E/AndroidRuntime( 883): at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:541)
E/AndroidRuntime( 883): at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:525)
E/AndroidRuntime( 883): at android.support.v4.app.DialogFragment.show(DialogFragment.java:123)
E/AndroidRuntime( 883): at com.myapp.ui.dialogs.TwoButtonDialogFragment.showDialog(TwoButtonDialogFragment.java:84)
Run Code Online (Sandbox Code Playgroud)
我的对话框显示在AsyncTask.onPostExecute()上,以显示对用户的http响应.在深入研究问题之后,我得出的结论是,只有当Activity暂停或停止时才会发生此异常,并且在其他版本的Android上不会发生此异常.我已经尝试使用commitAllowingStateLoss(),但它没有帮助,因为在DialogFragment.show()上抛出了异常.这是我的DialogFragment代码:
private static void showDialog(FragmentActivity activity, String title, String msg,
String positiveButtonText, String negativeButtonText, int id, Bundle args) {
if (activity.isFinishing()) {
return;
}
FragmentManager fmgr = activity.getSupportFragmentManager();
FragmentTransaction ft = fmgr.beginTransaction();
Fragment prev = fmgr.findFragmentByTag(TAG);
if (prev != …Run Code Online (Sandbox Code Playgroud) android android-fragments android-4.0-ice-cream-sandwich android-dialogfragment
我有一个注册到事件总线的splashscreen Fragment:
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
Run Code Online (Sandbox Code Playgroud)
如果屏幕进入自动锁定(或任何其他可以调用onStop的事件),则容器活动将进入onStop,并且该片段不再能够接收(网络)事件.我正在考虑将 "取消注册"逻辑移动到onDestroy方法.这是个好主意吗?
我在manager.popBackStack行下面收到此错误。有没有解决的办法?它确实发生了。
public void updateView(Fragment fragment) {
IFragment currentFragment = (IFragment)fragment;
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = manager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment);
if(currentFragment != null)
{
if(currentFragment.isRoot())
{
manager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
else
{
fragmentTransaction.addToBackStack("test");
}
}
fragmentTransaction.commitAllowingStateLoss();
if(drawerManager.DrawerLayout != null) {
drawerManager.DrawerLayout.closeDrawer(drawerManager.DrawerList);
}
}
Run Code Online (Sandbox Code Playgroud)
致命异常:java.lang.IllegalStateException:在android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager。的android.support.v4.app.FragmentManagerImpl.popBackStack(FragmentManager.java:799)的com.exposure.activities.BaseActivity.updateView(BaseActivity.java:239)的com.exposure.activities.events.EventActivity的java:2067) com.exposure.activities.events.EventActivity.getData(EventActivity.java:117)处的.setupEvent(EventActivity.java:204)com.exposure处com.exposure.utilities.ActivityContainer.getData(ActivityContainer.java:83)处的。 android.os.AsyncTask上的utilities.DataTask.onPostExecute(DataTask.java:37)。完成(AsyncTask.java:695)于android.os.AsyncTask.-wrap1(未知源)于android.os.AsyncTask $ InternalHandler.handleMessage(AsyncTask.java:712)于android.os.Handler.dispatchMessage(Handler.java :105),位于android.os.Looper.loop(Looper.java:164),位于com。的java.lang.reflect.Method.invoke(Method.java),位于android.app.ActivityThread.main(ActivityThread.java:6938) .android.internal.os.Zygote $ MethodAndArgsCaller.run(Zygote.java:327)在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)164),位于android.app.ActivityThread.main(ActivityThread.java:6938),位于com.android.internal.os.Zygote $ MethodAndArgsCaller.run(Zygote.java)的java.lang.reflect.Method.invoke(Method.java)处:327),位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)164),位于android.app.ActivityThread.main(ActivityThread.java:6938),位于com.android.internal.os.Zygote $ MethodAndArgsCaller.run(Zygote.java)的java.lang.reflect.Method.invoke(Method.java)处:327),位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)