【问题标题】:Activity in backstack raises java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState - Android后台堆栈中的活动引发 java.lang.IllegalStateException:onSaveInstanceState 后无法执行此操作 - Android
【发布时间】:2018-06-24 09:02:20
【问题描述】:

我正在开发一个有 2 个活动的 android 应用程序,第一个是 MainActivity,第二个是 UpdateActivity。在我的主要活动中,我有片段,在这些片段中,我使用下面给出的代码使用 childFragmentManager 嵌套片段的一层,

fun changeFragmentTransfer(int: Int,index : Int? = null){
    fragment = when(int) {
        0 -> DemoLocalFragment.newInstance(10, "")
        1 -> ConfigureLocalFragment.newInstance("","")
        2 -> LocalListingFragment.newInstance("","")
        else -> DetailLocalFragment.newInstance(index!!,"")
    }
    if (index == null)
        childFragmentManager
                .beginTransaction()
                .replace(R.id.baseLocalFrameLayout,fragment).commit()
    else {
        (activity as MainActivity).replaceFrameInMainActivity(fragment!!)
    }
}

如果我在执行此函数后打开 UpdateActivity 一切正常但如果我在执行到达这一点之前从 MainActivity 启动 UpdateActivity 则我的应用程序崩溃。

我不明白为什么当 MainActivity 在后台堆栈中时这段代码首先运行。

我检查了这些与同一主题相关的问题link1link2link3link4,但这里他们建议使用 commitAllowingStateLoss() 而不是 commit() 我买不起,因为我的片段依赖于这个保存的实例状态。那么是否有另一种解决方案可以让我保留已保存的实例状态。

我得到的错误如下。

进程:com.idea_implement_india.bloombench_and_kossine.iotcontrollerapp,PID:21132 java.lang.IllegalStateException:onSaveInstanceState 后无法执行此操作 在 android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:2053) 在 android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:2079) 在 android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:678) 在 android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:632) 在 com.idea_implement_india.bloombench_and_kossine.iotcontrollerapp.Fragments.BaseLocalFragment.changeFragmentTransfer(BaseLocalFragment.kt:94) 在 com.idea_implement_india.bloombench_and_kossine.iotcontrollerapp.Fragments.BaseLocalFragment.changeFragmentTransfer$default(BaseLocalFragment.kt:84) 在 com.idea_implement_india.bloombench_and_kossine.iotcontrollerapp.Fragments.DemoLocalFragment$subHandler$1.handleMessage(DemoLocalFragment.kt:141) 在 android.os.Handler.dispatchMessage(Handler.java:107) 在 android.os.Looper.loop(Looper.java:238) 在 android.app.ActivityThread.main(ActivityThread.java:6016) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:937) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:798)

在这个错误行中

com.idea_implement_india.bloombench_and_kossine.iotcontrollerapp.Fragments.BaseLocalFragment.changeFragmentTransfer(BaseLocalFragment.kt:94)

对应代码中的这一行

    childFragmentManager
            .beginTransaction()
            .replace(R.id.baseLocalFrameLayout,fragment).commit()

如果有人知道此问题的任何替代解决方案,请告知。 先感谢您。

【问题讨论】:

    标签: android android-fragments kotlin


    【解决方案1】:

    即使您的 MainActivity 在后台堆栈中,此代码也可能会执行,因为 commit() 函数以异步方式处理片段事务。您的 Fragment 会在稍后的某个时间点添加,但不受时间限制。

    解决这个问题的一种方法是使用commitNow() 而不是commit()。这将确保您的片段同步添加,并将保留 savedInstanceState。

    【讨论】:

    • 不,它没有用。但是我才意识到这个函数是在异步任务返回操作结果之后调用的。这可能是这种行为的原因吗?
    • 是的。这很重要,因为活动必须在执行片段事务时运行。在您的情况下,这不会发生,因为您正在等待异步响应。
    【解决方案2】:

    这个特殊问题已经在 P 版本的 Android 中得到解决。如果您的应用程序以操作系统版本 P 为目标,您将不会收到此错误,因为 onSaveInstanceState 方法将在 onStop() 之后调用。

    文档说

    如果调用,此方法将在应用程序的 onStop() 之后发生 针对以 Build.VERSION_CODES.P 开头的平台。为了 针对早期平台版本的应用程序此方法将 发生在 onStop() 之前,并且不能保证它是否 将在onPause()之前或之后发生

    【讨论】:

      猜你喜欢
      • 2012-12-20
      • 2018-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多