0

I am working on an android app which has 2 activities, first being MainActivity and Second is UpdateActivity. In my main activity, I have fragments and In these fragments, I am nesting one more layer of the fragment using childFragmentManager using the code given below,

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!!)
    }
}

Everything works just fine if I open UpdateActivity after this function is executed But if I start UpdateActivity from MainActivity before execution reaches this point then my app crashes.

I don't understand why this code runs in the first place when the MainActivity is in the back-stack.

I checked these questions related to the same topic link1 link2 link3 link4, but here they suggest to use commitAllowingStateLoss() instead of commit() which I can't afford as my fragments depend on this saved instance state. So is there an alternate solution in which I can preserve saved instance states.

The errors that I am getting is as follow.

Process: com.idea_implement_india.bloombench_and_kossine.iotcontrollerapp, PID: 21132 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:2053) at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:2079) at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:678) at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:632) at com.idea_implement_india.bloombench_and_kossine.iotcontrollerapp.Fragments.BaseLocalFragment.changeFragmentTransfer(BaseLocalFragment.kt:94) at com.idea_implement_india.bloombench_and_kossine.iotcontrollerapp.Fragments.BaseLocalFragment.changeFragmentTransfer$default(BaseLocalFragment.kt:84) at com.idea_implement_india.bloombench_and_kossine.iotcontrollerapp.Fragments.DemoLocalFragment$subHandler$1.handleMessage(DemoLocalFragment.kt:141) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:238) at android.app.ActivityThread.main(ActivityThread.java:6016) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:937) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:798)

Here in this error line

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

corresponds to this line in the code

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

If someone knows of any alternate solution to this problem then please do tell. Thank you in advance.

Mandar Sadye
  • 689
  • 2
  • 9
  • 30

2 Answers2

0

This code could potentially execute even when your MainActivity is in the back stack because commit() function handles fragment transaction in an async manner. Your Fragment is added at some point later which is not time bound.

One way to solve this would be using commitNow() instead of commit(). This would ensure synchronous addition of your fragment and will keep the savedInstanceState as well.

Udit
  • 1,037
  • 6
  • 11
  • no, it didn't work. But I just realized that the function is called after async task returns the result of the operation. Can that be the reason for such behaviour? – Mandar Sadye Jun 24 '18 at 09:28
  • Yes. It matters, as the activity has to be running while doing the fragment transaction. In your case, that won't happen as you are waiting for async reponse. – rafa Jun 25 '18 at 06:02
0

This particular issue has been solved in P version of Android. If your application targets OS version P, you won't get this error as onSaveInstanceState method will be called after onStop().

Documentation says

If called, this method will occur after onStop() for applications targeting platforms starting with Build.VERSION_CODES.P. For applications targeting earlier platform versions this method will occur before onStop() and there are no guarantees about whether it will occur before or after onPause()

rafa
  • 1,319
  • 8
  • 20