2012-08-24 35 views
42

實現一個應用程序,用戶可以登錄我有以下情況:如果用戶登錄進行操作否則啓動登錄活動的結果,如果結果是Activity.RESULT_OK執行操作。行動onActivityResult和「的onSaveInstanceState後的錯誤不能執行此操作」

我的問題是,要perfom行動是顯示DialogFragment,但在onActivityResult回調調用

DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel); 
newFragment.show(ft, "dialog") 

拋出一個異常:

Caused by: java.lang.IllegalStateException: 
Can not perform this action after onSaveInstanceState 

所以,我怎麼能解決這個問題?我想在提高的標誌存在,並在顯示的onResume對話,但我看到這個解決方案有點髒

編輯:添加更多的代碼(以下IM這個例子顯示DialogFragment

當動作按用戶要求:

... 
if (!user.isLogged()){ 
startActivityForResult(new Intent(cnt, Login.class), REQUEST_LOGIN_FOR_COMMENT); 
} 

在同一片段

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 
    if (requestCode == REQUEST_LOGIN_FOR_COMMENT && resultCode == Activity.RESULT_OK) { 
     FragmentTransaction ft = getFragmentManager().beginTransaction(); 
     DialogFragment newFragment = MyDialogFragment.newInstance(); 
     newFragment.show(ft, "dialog") 
    } 
} 

如果在登錄活動的用戶登錄調用;

setResult(Activity.RESULT_OK); 
finish(); 
+0

我想你應該發佈整個代碼。看起來像你試圖顯示對話框後繼續 – nandeesh

+0

編輯的問題:D – Addev

+1

檢查http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html瞭解爲什麼發生這種情況 – Maragues

回答

94

我想出的最好的東西是不使用.show()而是做到這一點。

CheckinSuccessDialog dialog = new CheckinSuccessDialog(); 
//dialog.show(getSupportFragmentManager(), null); 
FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
ft.add(dialog, null); 
ft.commitAllowingStateLoss(); 
+2

儘管它適用於我,但我覺得不安全,因爲我們排除了2個變量:mDismissed = false; mShownByMe = true;上述變量正在原始顯示功能中進行修改。 –

+2

謝謝,commitAllowingStateLoss爲我解決了這個問題 –

+0

mDismissed和mShowByMe似乎是專門用於跟蹤對話是否由外部調用顯示/隱藏的變量。換句話說,他們正是爲了補償這種事情。 –

9

以下是對我適用的解決方法。

private void alert(final String message) { 
    Handler handler = new Handler(Looper.getMainLooper()); 
    handler.post(new Runnable() { 
     public void run() { 
      AlertDialogFragment alertDialogFragment = AlertDialogFragment.newInstance(message); 
      alertDialogFragment.show(getFragmentManager(), ALERT_DIALOG_FRAGMENT); 
     } 
    });   
} 
4

如果使用DialogFragment,只爲我工作的事情是擯棄dissmissAllowingStateLoss的片段()

3

我只需檢查活動是否被破壞。

if (!getActivity().isFinishing()) { 
    DialogFragment fragment = MyFragment.newInstance(); 
    fragment.show(getActivity().getSupportFragmentManager(), MyFragment.TAG); 
} 
1

覆蓋show(Fragment manager, String tag)函數允許狀態丟失,並通過反射從origibal功能改變mDismissed = false;mShownByMe = true;

public class DialogParent extends DialogFragment { 

    @Override 
    public void show(FragmentManager manager, String tag) { 
     try { 
      Field mDismissed = DialogFragment.class.getDeclaredField("mDismissed"); 
      Field mShownByMe = DialogFragment.class.getDeclaredField("mShownByMe"); 
      mDismissed.setAccessible(true); 
      mShownByMe.setAccessible(true); 
      mDismissed.setBoolean(this, false); 
      mShownByMe.setBoolean(this, true); 
     } catch (NoSuchFieldException e) { 
      e.printStackTrace(); 
     } catch (IllegalAccessException e) { 
      e.printStackTrace(); 
     } 
     FragmentTransaction ft = manager.beginTransaction(); 
     ft.add(this, tag); 
     ft.commitAllowingStateLoss(); 
    } 
} 
+0

您也可以用try-catch包圍父節點方法,在catch中添加對話框並使用調用'commitAllowingStateLoss()'的事務。這樣你就不需要任何反思。 – SimonSimCity

0

這真正的作品。

CheckinSuccessDialog dialog = new CheckinSuccessDialog(); 
//dialog.show(getSupportFragmentManager(), null); 
FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
ft.add(dialog, null); 
ft.commitAllowingStateLoss(); 

但是卻仍然很糟糕,因爲出現錯誤「的活動已被破壞」

ava.lang.IllegalStateException: Activity has been destroyed fragmentTransaction.commitAllowingStateLoss(); 

所以我的解決辦法就是增加檢查if (!isFinishing()&&!isDestroyed())

CheckinSuccessDialog fragment = CheckinSuccessDialog.newInstance(); 

    if (fragment instanceof DialogFragment) { 
       DialogFragment dialog = (DialogFragment) fragment; 
       if (!dialog.isAdded()) { 
        fragmentTransaction.add(dialog, 
          CheckinSuccessDialog.class.getName()); 
        if (!isFinishing()&&!isDestroyed()) { 
         fragmentTransaction.commitAllowingStateLoss(); 
        } 
       } 
上解僱

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 
     Fragment fragment = getSupportFragmentManager().findFragmentByTag(CheckinSuccessDialog.class.getName()); 
     if (fragment != null && fragment instanceof DialogFragment) { 
      DialogFragment dialog = (DialogFragment) fragment; 
      dialog.dismiss(); 
      if (!isFinishing()&&!isDestroyed()) { 
       fragmentTransaction.commitAllowingStateLoss(); 
      } 
     } 
0

這個例外是t在FragmentManager已經保存其狀態之後,只要FragmentTrasaction被提交就可以接受。簡單而乾淨的方法是在顯示DialogFragment之前檢查FragmentManager是否已保存狀態。

if(!getSupportFragmentManager.isStateSaved()) { 
    MyDialogFragment dialogFragment = new MyDialogFragment() 
    dialogFragment.show(getSupportFragmentManager, TAG); 
} 
相關問題