2012-08-24 53 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); 
} 
相关问题