2014-01-22 54 views
1

我使用这个代码,以我的看法加载到DialogFragment:DialogFragment导致IllegalStateException异常

@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; 
} 

这个代码是在我的自定义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); 

我已经测试此代码,但在谷歌Analytics(分析)我看到_parentFragment.dismiss();原因 - >IllegalStateException (@SyncPopup$8:onPostExecute:221) {main}

我想它有什么做的,因为的AsyncTask我还获得这个问题与其他DialogFragments在哪里使用相同的模式。

我做错了什么? 我已经读过,您不应该使用-> getDialog().dismiss()关闭DialogFragment,但事实并非如此。我通过对我传入我的自定义视图的引用进行解雇来关闭它。

UPDATE:

不能说为什么,但现在除了内容时发生在我的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. 

,现在我想这样的:

@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); 
    } 

干杯, 斯特凡

+0

我们展示的堆栈跟踪 – alecnash

+0

我没有一个。我不能在我的测试设备,并在谷歌Analytics(分析)重现此我只看到 - >“1 \t IllegalStateException异常(@ SyncPopup $ 8:onPostExecute:221){主}” – stefan

+0

谷歌分析吮吸收集例外。 –

回答

5

您不能执行片段交易活动时该片段属于背景。由于您的对话框实际上是一个片段,因此解除它会触发片段事务。我猜你使用的AsyncTask通过调用onPostExecute来终止它的执行,而保存用于启动它的片段的活动在后台。你看,那里有IllegalStateException被抛出。

至少有一些解决方法。最简单的方法就是重写UI设计,避免显示对话框来显示任务的进度。这是关于Dialogs的官方文档指南中的建议,位于右侧的第一个旁边,就在绿色垂直条的旁边。

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

+0

非常感谢!现在,我很清楚。我实际上认为Fragments可以做所有活动可以做的事情,因为他们有自己的生命周期。我的应用程序有很多功能,我认为这是一种很好的模式,可以将功能分离并将其放置到弹出窗口中,而不是将所有内容放在活动中。 – stefan

相关问题