DialogFragment导致IllegalStateException

ste*_*fan 1 android android-layout android-fragments

我正在使用此代码将我的视图加载到DialogFragment:

    @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    SyncPopup syncPopup = new SyncPopup(getActivity(), this,_callback);

    getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
    getDialog().getWindow().setSoftInputMode(STYLE_NO_INPUT);
    getDialog().setCanceledOnTouchOutside(false);


    return syncPopup;
}
Run Code Online (Sandbox Code Playgroud)

这段代码在我的自定义DialogFragment中.所以this指向DialogFragment.SyncPopup保存了我的所有视图逻辑.我正在使用这种模式,以便我可以在其他地方重用SyncPopup.

在我的SyncPopup中,我正在运行AsyncTask,onPostExecute我希望关闭DialogFragment.- > _parentFragment通过构造函数注入,参见上面的代码(使用this指针).

SyncInfo si = new SyncInfo(email, Start, End);
        new AsyncTask<SyncInfo, Void, String>() {
            @Override
            protected void onPostExecute(String result) {
                super.onPostExecute(result);

                _callback.onSyncFinish();
                _parentFragment.dismiss();

            }

            @Override
            protected String doInBackground(SyncInfo... params) {
                SyncInfo si = params[0];
                return Cache.sync(si.Email, si.Start, si.End);
            }
        }.execute(si);
Run Code Online (Sandbox Code Playgroud)

我已经测试了这段代码,但在Google Analytics中,我看到了_parentFragment.dismiss();原因 - >IllegalStateException (@SyncPopup$8:onPostExecute:221) {main}

我想它与AsyncTask无关,因为我也使用其他DialogFragments来解决这个问题,我使用相同的模式.

我做错了吗?我已经读过你不应该关闭DialogFragment,-> getDialog().dismiss()但事实并非如此.我通过调用我传递到自定义视图的引用上的dismiss来关闭它.

更新:

不能说为什么,但现在我的android 4.03设备上出现异常,而我试图调试其他东西.所以我可以提供堆栈跟踪:

Shutting down VM
 threadid=1: thread exiting with uncaught exception (group=0x40c131f8)
 FATAL EXCEPTION: main
 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
    at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1343)
    at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1354)
    at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
    at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
    at android.support.v4.app.DialogFragment.dismissInternal(DialogFragment.java:189)
    at android.support.v4.app.DialogFragment.dismiss(DialogFragment.java:155)
    at com.mxp.time.popups.SyncPopup$8.onPostExecute(SyncPopup.java:239)
    at com.mxp.time.popups.SyncPopup$8.onPostExecute(SyncPopup.java:1)
    at android.os.AsyncTask.finish(AsyncTask.java:602)
    at android.os.AsyncTask.access$600(AsyncTask.java:156)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4493)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:788)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
    at dalvik.system.NativeStart.main(Native Method)
 Sending signal. PID: 24095 SIG: 9
 GC_CONCURRENT freed 1081K, 21% free 13393K/16747K, paused 4ms+3ms
 Starting setup.
Run Code Online (Sandbox Code Playgroud)

现在我正在尝试这个:

@Override
    public void onSaveInstanceState(Bundle outState) {
        //first saving my state, so the bundle wont be empty.
        //http://code.google.com/p/android/issues/detail?id=19917
        outState.putString("WORKAROUND_FOR_BUG_19917_KEY", "WORKAROUND_FOR_BUG_19917_VALUE");
        super.onSaveInstanceState(outState);
    }
Run Code Online (Sandbox Code Playgroud)

干杯,斯特凡

Giu*_*lli 5

当片段所属的活动位于后台时,您无法执行片段事务.由于您的对话框实际上是一个片段,因此解除它会触发片段事务.我猜AsyncTask你正在使用解除对话框通过调用终止其执行,onPostExecute而保存用于启动它的片段的活动是在后台.瞧,那里有IllegalStateException抛出.

至少有几个解决方法.最简单的方法是重新设计您的UI设计,避免显示任务的对话框.这是关于Dialogs的官方文档指南中的建议,在右边的第一个旁边,就在绿色竖条旁边.

我所知道的另一种可能的解决方案稍微复杂一点.嗯,这只是一种不同的复杂性:代码,而不是用户界面设计.您需要使用a Handler来收集来自的消息AsyncTask.不是直接解除对话框,而是AsyncTask向处理程序发送已完成的消息.处理程序接收消息并处理它,解除该片段.但是,只要持有它的活动进入后台(例如onPause)并且从后台恢复(例如,在),处理程序必须能够暂停和恢复消息处理onResume.这样,当活动在后台进行,并且AsyncTask完成触发对话框解雇时,处理程序接收解雇消息,但保持它直到活动恢复,现在可以安全地执行隐含的片段事务.