Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/196.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 提交时onSaveInstanceState之后无法执行此操作_Android - Fatal编程技术网

Android 提交时onSaveInstanceState之后无法执行此操作

Android 提交时onSaveInstanceState之后无法执行此操作,android,Android,我在ft.commit()时遇到异常,我不知道为什么 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1448) at android.support.v4.app.FragmentManage

我在
ft.commit()时遇到异常,我不知道为什么

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
    at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1448)
    at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1466)
    at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:634)
    at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:613)
    at MainActivity.attachFragment(MainActivity.java:242)
    at MainActivity.attachFragment(MainActivity.java:225)
    at MainActivity.showHome(MainActivity.java:171)
    at MainActivity.onComplete(MainActivity.java:278)
    at MDownloadManager.onDownloadComplete(MDownloadManager.java:83)
    at DownloadRequestQueue$CallBackDelivery$2.run(DownloadRequestQueue.java:61)
    at android.os.Handler.handleCallback(Handler.java:733)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:149)
    at android.app.ActivityThread.main(ActivityThread.java:5257)
    at java.lang.reflect.Method.invokeNative(Method.java)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
    at dalvik.system.NativeStart.main(NativeStart.java)
这是我的方法,崩溃即将发生

FragmentManager     fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();

if(addToBackStack) {
    ft.addToBackStack(null);
    ft.add(R.id.frame_container, fragment, tag);
} else {
    ft.replace(R.id.frame_container, fragment, tag);
}

ft.commit();
你知道怎么了吗


在我的项目中,我不使用
onSaveInstanceState

这很简单,在调用
onSaveInstanceState(Bundle outState)
后,您无法在活动中提交片段事务。什么时候调用代码


发生配置更改时,
onSavedInstanceState
作为活动生命周期的一部分被调用。您无法控制它。

方法是活动生命周期的一部分。所以,即使您没有显式地调用它,它也会在某个时刻被您的活动调用

所以问题是,在活动生命周期中,您在哪里使用了您向我们展示的代码? 一种解决方法是对片段事务使用而不是提交


(您应该阅读链接中的描述,看看是否可以使用此方法)

我也有同样的问题,但我可以通过重写onSaveInstanceState并注释调用其super的行来解决这个问题,就像片段中的这样

@Override
public void onSaveInstanceState(Bundle outState) {
 //   super.onSaveInstanceState(outState);
}
希望这能有所帮助

希望这会有所帮助

编辑1:经过进一步研究,这是一个已知的支持包

如果您需要保存实例,并将某些内容添加到您的
outState
Bundle
,您可以使用以下方法:

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putString("WORKAROUND_FOR_BUG_19917_KEY", "WORKAROUND_FOR_BUG_19917_VALUE");
    super.onSaveInstanceState(outState);
}
EDIT2:如果您试图在您的
活动
在后台消失后执行事务,也可能发生这种情况。要避免这种情况,您应该使用
commitAllowingStateLoss()

EDIT3:根据我的记忆,上述解决方案解决了早期support.v4库中的问题。但如果您对此仍有疑问,您还必须阅读的博客: 博客文章的摘要(但我强烈建议您阅读):

  • 在前蜂窝上的
    onPause()
    和后蜂窝上的
    onStop()
    之后,决不执行
    commit()
    事务
  • 活动
    生命周期方法中提交事务时要小心。使用
    onCreate()
    onResumeFragments()
    onPostResume()
  • 避免在异步回调方法内执行事务
  • 只能在万不得已的情况下使用
    committellowingstateloss()

重写saveInstanceState是一种不一定适用于所有场景的黑客行为。此外,使用commitAllowingStateLoss()是危险的,可能会导致UI异常

我们需要了解,在活动状态丢失后尝试提交片段时,会遇到IllegalStateException—活动不在前台(以了解更多关于活动状态的信息)。因此,为了避免(解决)这个异常,我们只需延迟片段事务,直到状态恢复

声明两个私有布尔变量

public class MainActivity extends AppCompatActivity {

    //Boolean variable to mark if the transaction is safe
    private boolean isTransactionSafe;

    //Boolean variable to mark if there is any transaction pending
    private boolean isTransactionPending;
现在在onPostResume()和onPause中,我们设置和取消设置布尔变量isTransactionSafe。这样做的目的是,只有在活动处于前景时,才将转移标记为安全的,这样就不会有状态丢失的可能

/*
onPostResume is called only when the activity's state is completely restored. In this we will
set our boolean variable to true. Indicating that transaction is safe now
 */
public void onPostResume(){
    super.onPostResume();
    isTransactionSafe=true;
}
/*
onPause is called just before the activity moves to background and also before onSaveInstanceState. In this
we will mark the transaction as unsafe
 */

public void onPause(){
    super.onPause();
    isTransactionSafe=false;

}

private void commitFragment(){
    if(isTransactionSafe) {
        MyFragment myFragment = new MyFragment();
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.frame, myFragment);
        fragmentTransaction.commit();
    }
}
到目前为止,我们所做的将从IllegalStateException中保存,但如果在活动移动到后台后完成,我们的交易将丢失,有点像CommittelLowstateLoss()。为了帮助实现这一点,我们使用了isTransactionPending布尔变量

public void onPostResume(){
   super.onPostResume();
   isTransactionSafe=true;
/* Here after the activity is restored we check if there is any transaction pending from
the last restoration
*/
   if (isTransactionPending) {
      commitFragment();
   }
}


private void commitFragment(){

 if(isTransactionSafe) {
     MyFragment myFragment = new MyFragment();
     FragmentManager fragmentManager = getFragmentManager();
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
     fragmentTransaction.add(R.id.frame, myFragment);
     fragmentTransaction.commit();
     isTransactionPending=false;
 }else {
     /*
     If any transaction is not done because the activity is in background. We set the
     isTransactionPending variable to true so that we can pick this up when we come back to
foreground
     */
     isTransactionPending=true;
 }
}

以下是使用Kotlin更新的解决方案。有关详细信息,请查看本文:


如果您在项目中使用协程,您可以轻松地确保代码在生命周期状态至少已启动且未销毁时运行

lifecycleScope.launchWhenStarted{}

很好,IrshadKumail。谢谢@Isaackingston我认为这个答案比任何代码都更有效。检查链接。
lifecycleScope.launchWhenStarted{}