2013-03-13 76 views
3

此前解决“的onSaveInstanceState后无法执行此操作”,我们有没有问题,显示以下DialogFragment任何副作用,使用commitAllowingStateLoss

enter image description here

// Triggered by button click. 
private void openFromCloud() {  
    LoadFromCloudTaskFragment loadFromCloudTaskFragment = new LoadFromCloudTaskFragment(); 
    FragmentManager fm = this.getSupportFragmentManager(); 
    fm.beginTransaction().add(loadFromCloudTaskFragment, "loadFromCloudTaskFragment").commit(); 
} 

但是,如果我们往往会显示在按下以下Intent上的确定按钮后,将出现相同的DialogFragment,则会发生错误。

enter image description here

private void openFromCloud() {  
    startActivityForResult(Utils.getGoogleAccountCredential().newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER); 
} 

@Override 
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { 
    switch (requestCode) { 
    case REQUEST_ACCOUNT_PICKER: 
     if (resultCode == RESULT_OK && data != null && data.getExtras() != null) { 
      String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); 
      if (accountName != null) { 
       Utils.getGoogleAccountCredential().setSelectedAccountName(accountName); 
       LoadFromCloudTaskFragment loadFromCloudTaskFragment = new LoadFromCloudTaskFragment(); 
       FragmentManager fm = getSupportFragmentManager(); 
       fm.beginTransaction().add(loadFromCloudTaskFragment, "loadFromCloudTaskFragment").commit(); 
      } 
     } 
    break; 
    } 
} 

下面是详细的错误日志

FATAL EXCEPTION: main 
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { (has extras) }} to activity {org.yccheok.xxx.gui/org.yccheok.xxx.gui.XXXFragmentActivity}: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 
    at android.app.ActivityThread.deliverResults(ActivityThread.java:3141) 
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:3184) 
    at android.app.ActivityThread.access$1100(ActivityThread.java:130) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1243) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:137) 
    at android.app.ActivityThread.main(ActivityThread.java:4745) 
    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:786) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
    at dalvik.system.NativeStart.main(Native Method) 
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 
    at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1299) 
    at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1310) 
    at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:541) 
    at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:525) 
    at org.yccheok.xxx.gui.XXXFragmentActivity$1.run(XXXFragmentActivity.java:107) 
    at android.app.Activity.runOnUiThread(Activity.java:4591) 
    at org.yccheok.xxx.gui.XXXFragmentActivity.onActivityResult(XXXFragmentActivity.java:102) 
    at android.app.Activity.dispatchActivityResult(Activity.java:5192) 
    at android.app.ActivityThread.deliverResults(ActivityThread.java:3137) 
    ... 11 more 

使用commitAllowingStateLoss代替commit我可以简单地 “解决” 问题。

fm.beginTransaction().add(loadFromCloudTaskFragment, "loadFromCloudTaskFragment").commitAllowingStateLoss(); 

我真的不明白关于commitAllowingStateLoss的文档。

与commit()类似,但允许在保存活动的 状态后执行提交。这很危险,因为如果 该活动需要稍后从其状态恢复,则该提交可能会丢失,所以这个应该只用于UI状态在用户意外改变 的情况。

这是基于从建议getting exception "IllegalStateException: Can not perform this action after onSaveInstanceState"

我真的不明白了吧它是好的,对UI状态对用户意外更改。?我可否知道使用commitAllowingStateLoss有什么可能的副作用?我可以产生这种副作用的任何步骤?

+0

查看此[**博客文章**](http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html)以获取有关此异常发生原因的更多信息。 – 2013-08-20 22:37:09

回答

5

我能想到的唯一的事情就是种族情况事件。

想象一下在设备正在拨打commitAllowingStateLoss()之前旋转的情况。据我所知,会发生以下情况:

  • onSaveInstanceState()回调(活性店是状态没有碎片,此刻目前(因为你有没有犯任何事情)
  • commitAllowingStateLoss执行添加片段到活动
  • Activity被重建,恢复它的状态的时刻,当有没有你的片段添加

在我看来,它造成难以预料的情况,如:

  • java.lang.IllegalStateException: Failure saving state: FragmentB has target not in fragment manager: FragmentA如果您使用Fragment.setTargetFragment()以任何理由
  • 您的片段可以简单地从该视图

反正失踪,我不是100%确定的,但我的应用程序中有很多意外的例外情况java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState,并试图找到解决方案。

+0

你解决了这个问题吗? – Hades 2014-01-16 01:41:28

+0

看看[这里](http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html) – 2014-01-16 09:06:54

+0

nah anh我发现问题是什么......这是因为试图成为目标片段的片段不在后台 – Hades 2014-01-17 04:21:38

2

可能你没有这个问题了。我遇到了类似的问题。我解决了在onResume函数中放置片段转换代码。我已经放了一个标志来表明结果是否正确。如果它是真的,那么在onResume方法中,我确实转换到了其他片段。

+0

是的,我也相信这是做到这一点的正确方法。在这种情况下也不需要使用'commitAllowingStateLoss()'。 :) – 2013-08-20 22:42:23

+0

如果我们在这里讨论的建议不明确......这个[**答案**](http://stackoverflow.com/q/16265733/844882)使用这种方法,并很好地解决了这个问题。 – 2013-08-20 22:52:16

0

你可以看到如下代码Activity.java

protected void onSaveInstanceState(Bundle outState) { 
    outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState()); 
    Parcelable p = mFragments.saveAllState(); 
    if (p != null) { 
     outState.putParcelable(FRAGMENTS_TAG, p); 
    } 
    getApplication().dispatchActivitySaveInstanceState(this, outState); 
} 

关键代码===> mFragments.saveAllState()

,如果你以后的onSaveInstanceState然后提交该片段的状态将不保存