IllegalStateException:在onsaveinstanceestate之后不能执行此操作;

我有一个Live Android应用程序,从市场上我收到了以下堆栈跟踪,我不知道为什么它会发生,因为它不是发生在应用程序代码中,而是由应用程序的一些或其他事件引起的(假设)

我没有使用Fragments,仍然有FragmentManager的引用。 如果有人能解释一些隐藏的事实,以避免这类问题:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1109)
at android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:399)
at android.app.Activity.onBackPressed(Activity.java:2066)
at android.app.Activity.onKeyDown(Activity.java:1962)
at android.view.KeyEvent.dispatch(KeyEvent.java:2482)
at android.app.Activity.dispatchKeyEvent(Activity.java:2274)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1720)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1258)
at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewRoot.deliverKeyEventPostIme(ViewRoot.java:2851)
at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2824)
at android.view.ViewRoot.handleMessage(ViewRoot.java:2011)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4025)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)
252133 次浏览

如果你试图在你的片段活动的onSaveInstanceState()被调用之后执行片段转换,就会发生这样的异常。

可能发生这种情况的一个原因是,当活动停止时,如果你让AsyncTask(或Thread)运行。

调用onSaveInstanceState()之后的任何转换都可能丢失,如果系统回收活动以获取资源并稍后重新创建它。

当用户旋转屏幕以便加载与新方向相关的资源时,onSaveInstance将被调用。

有可能这个用户旋转了屏幕,然后按了后退按钮(因为也有可能这个用户在使用你的应用程序时摸不着他们的手机)

这是我迄今为止遇到的最愚蠢的错误。我有一个Fragment应用程序工作完美的API & lt;11,和API > 11上的Force Closing

我真的无法弄清楚它们在Activity生命周期内对saveInstance的调用中发生了什么变化,但我在这里是如何解决这个问题的:

@Override
protected void onSaveInstanceState(Bundle outState) {
//No call for super(). Bug on API Level > 11.
}

我只是没有调用.super(),一切都工作得很好。我希望这将为您节省一些时间。

经过进一步研究,这是支持包中已知的错误

如果你需要保存实例,并在你的outState Bundle中添加一些东西,你可以使用以下方法:

@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("WORKAROUND_FOR_BUG_19917_KEY", "WORKAROUND_FOR_BUG_19917_VALUE");
super.onSaveInstanceState(outState);
}

如果你试图在你的Activity在后台消失后执行一个事务,这也可能发生。为了避免这种情况,你应该使用commitAllowingStateLoss()

上面的解决方案修复了早期支持中的问题。v4库。但是如果你仍然对此有问题,你必须也要阅读@AlexLockwood的博客:Fragment Transactions &活动状态损失

博客文章的总结(但我强烈建议你阅读它):

  • 在pre-Honeycomb上的onPause()和post-Honeycomb上的onStop()之后的从来没有 commit()事务
  • Activity生命周期方法中提交事务时要小心。使用 onCreate()onResumeFragments()onPostResume()
  • 避免在异步回调方法中执行事务
  • commitAllowingStateLoss()只能作为最后的手段
我用onconfigurationchanged解决了这个问题。诀窍是根据android活动的生命周期,当你显式地调用一个意图(相机意图,或任何其他一个);在这种情况下,activity被暂停,onsavedInstance被调用。当将设备旋转到与活动激活时不同的位置时;做分片操作,比如分片提交,会导致非法状态异常。对此有很多抱怨。这是关于android活动生命周期管理和正确的方法调用。 为了解决这个问题,我这样做了: 1 .重写activity的onsavedInstance方法,并确定当前屏幕方向(纵向或横向),然后在activity暂停之前设置你的屏幕方向。这样你就可以锁定你的活动的屏幕旋转,以防它被另一个活动旋转。 然后,覆盖onresume方法的activity,现在设置你的方向模式为传感器,这样onsaved方法被调用后,它会再次调用onconfiguration来正确处理旋转

你可以复制/粘贴这段代码到你的活动来处理它:

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);


Toast.makeText(this, "Activity OnResume(): Lock Screen Orientation ", Toast.LENGTH_LONG).show();
int orientation =this.getDisplayOrientation();
//Lock the screen orientation to the current display orientation : Landscape or Potrait
this.setRequestedOrientation(orientation);
}


//A method found in stackOverflow, don't remember the author, to determine the right screen orientation independently of the phone or tablet device
public int getDisplayOrientation() {
Display getOrient = getWindowManager().getDefaultDisplay();


int orientation = getOrient.getOrientation();


// Sometimes you may get undefined orientation Value is 0
// simple logic solves the problem compare the screen
// X,Y Co-ordinates and determine the Orientation in such cases
if (orientation == Configuration.ORIENTATION_UNDEFINED) {
Configuration config = getResources().getConfiguration();
orientation = config.orientation;


if (orientation == Configuration.ORIENTATION_UNDEFINED) {
// if height and widht of screen are equal then
// it is square orientation
if (getOrient.getWidth() == getOrient.getHeight()) {
orientation = Configuration.ORIENTATION_SQUARE;
} else { //if widht is less than height than it is portrait
if (getOrient.getWidth() < getOrient.getHeight()) {
orientation = Configuration.ORIENTATION_PORTRAIT;
} else { // if it is not any of the above it will defineitly be landscape
orientation = Configuration.ORIENTATION_LANDSCAPE;
}
}
}
}
return orientation; // return value 1 is portrait and 2 is Landscape Mode
}


@Override
public void onResume() {
super.onResume();
Toast.makeText(this, "Activity OnResume(): Unlock Screen Orientation ", Toast.LENGTH_LONG).show();
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
在Android源代码中查找导致此问题的原因,给出FragmentManagerImpl类(Activity中可用的实例)中的标志mStateSaved的值为true。当从Activity#onSaveInstanceState调用时保存后堆栈(saveAllState)时,它被设置为true。 之后,来自ActivityThread的调用不会使用FragmentManagerImpl#noteStateNotSaved()dispatch()中的可用重置方法重置此标志

在我看来,有一些可用的修复,这取决于你的应用程序正在做什么和使用:

的好方法

首先,我要宣传Alex Lockwood文章。然后,根据我目前所做的:

  1. 对于不需要保存任何状态信息的片段和活动,调用commitAllowStateLoss。摘自文档:

    允许在保存活动状态后执行提交。这是危险的,因为如果活动需要从其状态中恢复,提交可能会丢失,所以这应该只用于用户的UI状态意外改变是可以的情况下。如果片段显示只读信息,我想这是可以使用的。或者即使它们确实显示可编辑的信息,也可以使用回调方法来保留已编辑的信息。

  2. 就在事务提交之后(你刚刚调用了commit()),调用FragmentManager.executePendingTransactions()

不推荐的方法:

  1. 正如Ovidiu Latcu上面提到的,不要调用super.onSaveInstanceState()。但这意味着您将失去活动的整个状态以及片段状态。

  2. 覆盖onBackPressed,在那里只调用finish()。这应该是OK,如果你的应用程序不使用Fragments API;就像在super.onBackPressed中一样,调用了FragmentManager#popBackStackImmediate()

  3. 如果你同时使用Fragments API并且你的activity的状态是important/vital,那么你可以尝试使用反射API FragmentManagerImpl#noteStateNotSaved()调用。但这是一种破解,或者可以说是一种变通方法。我不喜欢它,但在我的情况下,这是相当可接受的,因为我有一个遗留应用程序的代码,使用弃用的代码(TabActivity和隐式LocalActivityManager)。

下面是使用反射的代码:

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
invokeFragmentManagerNoteStateNotSaved();
}


@SuppressWarnings({ "rawtypes", "unchecked" })
private void invokeFragmentManagerNoteStateNotSaved() {
/**
* For post-Honeycomb devices
*/
if (Build.VERSION.SDK_INT < 11) {
return;
}
try {
Class cls = getClass();
do {
cls = cls.getSuperclass();
} while (!"Activity".equals(cls.getSimpleName()));
Field fragmentMgrField = cls.getDeclaredField("mFragments");
fragmentMgrField.setAccessible(true);


Object fragmentMgr = fragmentMgrField.get(this);
cls = fragmentMgr.getClass();


Method noteStateNotSavedMethod = cls.getDeclaredMethod("noteStateNotSaved", new Class[] {});
noteStateNotSavedMethod.invoke(fragmentMgr, new Object[] {});
Log.d("DLOutState", "Successful call for noteStateNotSaved!!!");
} catch (Exception ex) {
Log.e("DLOutState", "Exception on worka FM.noteStateNotSaved", ex);
}
}

干杯!

< p >读 http://chris-alexander.co.uk/on-engineering/dev/android-fragments-within-fragments/ < / p > < p >的文章。 fragment. isresume()检查帮助我在onDestroyView w/o使用onSaveInstanceState方法

这对我很管用……我自己发现的…希望对你有所帮助!

1)不要有全局的“静态”FragmentManager / FragmentTransaction。

2) onCreate,总是初始化FragmentManager再次!

样本如下:-

public abstract class FragmentController extends AnotherActivity{
protected FragmentManager fragmentManager;
protected FragmentTransaction fragmentTransaction;
protected Bundle mSavedInstanceState;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSavedInstanceState = savedInstanceState;
setDefaultFragments();
}


protected void setDefaultFragments() {
fragmentManager = getSupportFragmentManager();
//check if on orientation change.. do not re-add fragments!
if(mSavedInstanceState == null) {
//instantiate the fragment manager


fragmentTransaction = fragmentManager.beginTransaction();


//the navigation fragments
NavigationFragment navFrag = new NavigationFragment();
ToolbarFragment toolFrag = new ToolbarFragment();


fragmentTransaction.add(R.id.NavLayout, navFrag, "NavFrag");
fragmentTransaction.add(R.id.ToolbarLayout, toolFrag, "ToolFrag");
fragmentTransaction.commitAllowingStateLoss();


//add own fragment to the nav (abstract method)
setOwnFragment();
}
}

我对这个问题的解决方案是

在片段中添加方法:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
guideMapFragment = (SupportMapFragment)a.getSupportFragmentManager().findFragmentById(R.id.guideMap);
guideMap = guideMapFragment.getMap();
...
}


@Override
public void onDestroyView() {
SherlockFragmentActivity a = getSherlockActivity();
if (a != null && guideMapFragment != null) {
try {
Log.i(LOGTAG, "Removing map fragment");
a.getSupportFragmentManager().beginTransaction().remove(guideMapFragment).commit();
guideMapFragment = null;
} catch(IllegalStateException e) {
Log.i(LOGTAG, "IllegalStateException on exit");
}
}
super.onDestroyView();
}

可能很糟糕,但找不到更好的了。

Android 4.2和支持库的源代码中修正了这个问题。[*]

有关原因(和解决方案)的详细信息,请参阅谷歌错误报告: http://code.google.com/p/android/issues/detail?id=19917 < / p >

如果你正在使用支持库,那么你不应该担心这个错误(很长时间)[*]。然而,如果你直接使用API(即不使用支持库的FragmentManager),并针对Android 4.2以下的API,那么你将需要尝试一种变通方法。

[*]在撰写本文时,Android SDK管理器仍在分发显示此错误的旧版本。

编辑我要在这里补充一些澄清,因为我显然莫名其妙地混淆了投票这个答案的人。

几种不同(但相关)的情况可能导致抛出此异常。我上面的回答是指问题中讨论的特定实例,即Android中的一个bug,随后已被修复。如果你因为其他原因得到这个异常,那是因为你在不应该的时候添加/删除了片段(在片段状态保存之后)。如果你处于这样的情况下,那么“嵌套片段- IllegalStateException“onSaveInstanceState后不能执行此操作””可能对你有用。

在显示你的片段之前简单地调用super.onPostResume (),或者在调用super.onPostResume()之后在onPostResume()方法中移动你的代码。这就解决了问题!

好吧,在尝试了以上所有的解决方案都没有成功(因为基本上我没有事务)。

在我的情况下,我使用alertdialog和ProgressDialog作为片段,有时,在旋转时,当请求FragmentManager时,错误会上升。

我找到了一个混合了许多类似帖子的变通方法:

这是一个3步解决方案,所有在你的FragmentActivity(在这种情况下,它被称为GenericActivity):

private static WeakReference<GenericActivity> activity = null; //To avoid bug for fragments: Step 1 of 3


@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//To avoid bug for fragments: Step 2 of 3
activity = new WeakReference<GenericActivity>(this);
}


@Override
public FragmentManager getSupportFragmentManager(){
//To avoid bug for fragments: Step 3 of 3
if (this == activity.get()) {
return super.getSupportFragmentManager();
}
return activity.get().getSupportFragmentManager();
}

在屏幕被锁定\blank并且Activity +对话框的实例状态被保存后,在对话框片段上调用dismiss()时也会发生这种情况。要绕过这个调用:

dismissAllowingStateLoss()

实际上,每次我解散一个对话框时,我都不再关心它的状态了,所以这样做是可以的——实际上你并没有失去任何状态。

当我在一个片段中使用startactivity时,我会得到这个异常;

当我改变使用startactivityforresult时,异常消失了:)

所以修复它的简单方法是使用startActivityForResult api:)

我得到这个异常时,我按下返回按钮取消意图选择器在我的地图片段活动。 我通过替换onResume()的代码来解决这个问题(我在那里初始化片段和提交事务)到onStart(),应用程序现在工作正常。

你可以使用FragmentActivity。onStart在popBackStackImmediate之前

是这样的:

public void backStackFragment() {
this.start();
getFragmentManager().popBackStackImmediate();
}


public void start(){
FragmentActivity a = getActivity();
if(a instanceof DepositPlanPadActivity){
((DepositPlanPadActivity)a).onStart();
}
if(a instanceof SmallChangePlanPad){
((SmallChangePlanPad)a).onStart();
}
if(a instanceof UserCenterActivity){
((UserCenterActivity)a).onStart();
}
}

http://jorryliu.blogspot.com/2014/09/illegalstateexception-can-not-perform.html

简单有效的解决方案:

遵循简单的步骤:

步骤1:覆盖各自片段中的onSaveInstanceState状态。并从中移除super method。

@Override
public void onSaveInstanceState(Bundle outState) {
};

步骤2:使用CommitAllowingStateLoss();而不是commit();而片段操作。

fragmentTransaction.commitAllowingStateLoss();

当我试图在onActivityForResult()方法中显示片段时,我总是得到这个,所以接下来的问题是:

  1. 我的活动暂停和停止,这意味着,onSaveInstanceState()已经被调用(对于pre-Honeycomb和post-Honeycomb设备)。
  2. 在任何结果的情况下,我使事务显示/隐藏片段,这导致这个IllegalStateException。

接下来我做的是:

  1. 增加了确定我想要的动作是否完成的值(例如,从camere - isPhotoTaken中拍摄照片)-它可以是布尔值或整数值,这取决于你需要多少不同的事务。
  2. 在重写onResumeFragments()方法中,我检查了我的值,并在我需要的片段事务之后。在这种情况下,commit()没有在onSaveInstanceState之后执行,因为状态是在onResumeFragments()方法中返回的。

经过研究,这个问题的解决方案是做你的片段提交在onresume。

来源:https://wenchaojames.wordpress.com/2013/01/12/illegalstateexception-from-onactivityresult/

我有同样的问题,得到IllegalStateException,但替换所有调用commit()与commitAllowingStateLoss()没有帮助。

罪魁祸首是调用DialogFragment.show()。

我用

try {
dialog.show(transaction, "blah blah");
}
catch(IllegalStateException e) {
return;
}

这样就成功了。好吧,我没有展示对话,但在这种情况下,这是可以的。

这是我的应用程序中唯一一个我第一次调用FragmentManager.beginTransaction()但从未调用commit()的地方,所以当我寻找“commit()”时,我没有找到它。

有趣的是,用户从未离开该应用。相反,出现的AdMob插页广告才是罪魁祸首。

我也有同样的问题,经过一天的分析,所有的文章,博客和stackoverflow,我找到了一个简单的解决方案。完全不要使用savedInstanceState,这是一行代码的条件。在片段代码上:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
.....

我有这个问题。但是我认为这个问题与commit和commitAllowStateLoss无关。

下面的堆栈跟踪和异常消息是关于commit()的。

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1341)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1352)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)

但是这个异常是由onBackPressed()引起的

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(Unknown Source)
at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(Unknown Source)
at android.support.v4.app.FragmentActivity.onBackPressed(Unknown Source)

它们都是由checkStateLoss()引起的

private void checkStateLoss() {
if (mStateSaved) {
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
if (mNoTransactionsBecause != null) {
throw new IllegalStateException(
"Can not perform this action inside of " + mNoTransactionsBecause);
}

mStateSaved在onSaveInstanceState之后为真。

这个问题很少发生。我从来没有遇到过这个问题。我不能再出现这个问题。

我找到了发行25517

它可能在下列情况下发生

  1. Back键在onSaveInstanceState之后,但在新活动开始之前被调用。

  2. 在代码中使用onStop()

我不确定问题的根源是什么。 所以我用了一个丑陋的方法

@Override
public void onBackPressed() {


try{
super.onBackPressed();
}catch (IllegalStateException e){
// can output some information here
finish();
}
}

我的用例:我在片段中使用侦听器通知活动发生了一些事情。我在回调方法上做了新片段提交。这对第一次来说非常有效。但是在方向改变时,活动被重新创建并保存实例状态。在这种情况下,片段不会再次创建,这意味着片段拥有旧的已销毁活动的侦听器。不管怎样,回调方法都会在动作时被触发。它进入了导致问题的被破坏的活动。解决方案是用当前活动片段重置侦听器。这就解决了问题。

我发现的是,如果另一个应用程序是对话类型,并允许触摸被发送到后台应用程序,那么几乎任何后台应用程序都会崩溃这个错误。 我认为我们需要在每次执行事务时检查实例是否保存或恢复

在我的例子中,有相同的错误异常,我把“onBackPressed()”放在一个可运行对象中(你可以使用你的任何视图):

myView.post(new Runnable() {
@Override
public void run() {
onBackPressed()
}
});

我不知道为什么,但它有效!

我在我的应用程序中有同样的问题。我已经解决了这个问题,只是在以前的类上调用super.onBackPressed();,并在当前类上使用该片段调用commitAllowingStateLoss()

你可能会调用fragmentManager.popBackStackImmediate();当活动暂停时。活动未完成,但处于暂停状态,且不在前台。你需要在popBackStackImmediate()之前检查activity是否被暂停。

我认为在这些操作之前调用FragmentActivity.onStateNotSaved()可能是目前最好的选择。

谢谢@gunar,但我认为有更好的方法。

医生说:

 * If you are committing a single transaction that does not modify the
* fragment back stack, strongly consider using
* {@link FragmentTransaction#commitNow()} instead. This can help avoid
* unwanted side effects when other code in your app has pending committed
* transactions that expect different timing.
*
* @return Returns true if there were any pending transactions to be
* executed.
*/
public abstract boolean executePendingTransactions();

所以使用commitNow替换:

fragmentTransaction.commit();
FragmentManager.executePendingTransactions()

这发生在你试图加载一个片段,但活动已改变其状态为onPause()。例如,当您试图获取数据并将其加载到活动中,但当用户单击某个按钮并移动到下一个活动时,就会发生这种情况。

你可以用两种方法解决这个问题

您可以使用transaction.commitAllowingStateLoss()而不是transaction.commit()来加载片段,但您可能最终会丢失已完成的提交操作。

确保activity在加载片段时处于恢复状态,而不是进入暂停状态。 创建一个布尔值,检查activity是否不进入onPause()状态

@Override
public void onResume() {
super.onResume();
mIsResumed = true;
}


@Override
public void onPause() {
mIsResumed = false;
super.onPause();
}

然后,而加载片段检查活动是否存在,只有当活动是前景时才加载。

if(mIsResumed){
//load the fragment
}

我注意到一些非常有趣的事情。我在我的应用程序中有打开手机图库的选项,设备询问要使用哪个应用程序,在那里我点击了对话框之外的灰色区域,看到了这个问题。我注意到我的活动如何从onPause, onSaveInstanceState回到onResume,它不访问onCreateView。我在onResume做交易。我最终做的是设置一个标志,在onPause上为负,但在createview上为真。如果onResume标志为真,则执行onCommit,否则为commitAllowingStateLoss。我可以继续浪费这么多时间但我想检查生命周期。我有一个sdkversion 23的设备,我没有得到这个问题,但我有另一个是21的设备,我看到了它。

我认为生命周期状态可以帮助防止这种崩溃从Android支持库v26.1.0开始,你可以有以下检查:

if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)){
// Do fragment's transaction commit
}

或者你可以试试:

Fragment.isStateSaved()

更多信息在这里 https://developer.android.com/reference/android/support/v4/app/Fragment.html isStateSaved () < / p >

解决这个问题的另一种生命周期方法是使用kotlin最新发布的lifecycle-ktx。

lifecycleScope.launchWhenResumed {
// your code with fragment or dialogfragment
}

闭包将在恢复状态后运行,因此即使在恢复状态后调用此方法 停止,它将在下一次恢复时安全执行

你也可以选择喜欢

lifecycleScope.launchWhenCreated
// or
lifecycleScope.launchWhenStarted

适合你的情况。

当销毁完成时,代码将被取消。

谷歌文档链接: https://developer.android.com/kotlin/ktx#lifecycle < / p >

当一个Fragment或AppCompatActivity的状态通过onSaveInstanceState()保存时,它的UI被认为是不可变的,直到ON_START被调用。在保存状态后尝试修改UI可能会导致应用程序导航状态的不一致,这就是为什么FragmentManager会抛出异常,如果应用程序在保存状态后运行FragmentTransaction。参见commit()了解详细信息。

LiveData通过避免在观察者的关联生命周期至少不是STARTED时调用它的观察者来避免这种边缘情况。在幕后,它在决定调用其观察者之前调用isAtLeast()。