2014-01-22 75 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

相關問題