BottomNavigator
BottomNavigator copied to clipboard
Can the BottomNavigator operate when placed in a Fragment?
Hello!
Our application is a single activity, and so each screen is a fragment. We currently have a splash screen fragment S
which, when completed, tells the hosting activity to replace it with a fragment T
that contains a BottomNavigationView
. In the onStart
method of T
, I initialize a BottomNavigator
. This results in the following exception:
Process: org.nypl.simplified.vanilla, PID: 11993
io.reactivex.exceptions.OnErrorNotImplementedException: The exception was not handled due to missing onError handler in the subscribe() method call. Further reading: https://github.com/ReactiveX/RxJava/wiki/Error-Handling | java.lang.IllegalStateException: FragmentManager is already executing transactions
at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:704)
at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:701)
at io.reactivex.internal.observers.LambdaObserver.onError(LambdaObserver.java:77)
at io.reactivex.internal.observers.LambdaObserver.onNext(LambdaObserver.java:67)
at hu.akarnokd.rxjava2.subjects.UnicastWorkSubject.drain(UnicastWorkSubject.java:258)
at hu.akarnokd.rxjava2.subjects.UnicastWorkSubject.subscribeActual(UnicastWorkSubject.java:159)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.Observable.subscribe(Observable.java:12253)
at io.reactivex.Observable.subscribe(Observable.java:12155)
at com.pandora.bottomnavigator.ActivityDelegate.onActivityStart(ActivityDelegate.kt:53)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at androidx.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:216)
at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeMethodsForEvent(ClassesInfoCache.java:194)
at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeCallbacks(ClassesInfoCache.java:185)
at androidx.lifecycle.ReflectiveGenericLifecycleObserver.onStateChanged(ReflectiveGenericLifecycleObserver.java:36)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:188)
at com.pandora.bottomnavigator.ActivityDelegate.<init>(ActivityDelegate.kt:44)
at com.pandora.bottomnavigator.BottomNavigator.onCreate(BottomNavigator.kt:399)
at com.pandora.bottomnavigator.BottomNavigator.access$onCreate(BottomNavigator.kt:36)
at com.pandora.bottomnavigator.BottomNavigator$Companion.onCreate(BottomNavigator.kt:323)
at org.nypl.simplified.ui.navigation.tabs.TabbedNavigationController$Companion.create(TabbedNavigationController.kt:70)
at org.nypl.simplified.main.MainFragment.onStart(MainFragment.kt:54)
at androidx.fragment.app.Fragment.performStart(Fragment.java:2632)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:915)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6939)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
Caused by: java.lang.IllegalStateException: FragmentManager is already executing transactions
at androidx.fragment.app.FragmentManagerImpl.ensureExecReady(FragmentManagerImpl.java:1660)
Is there something special I need to do to run a bottom navigator inside a fragment? I suspect that this might be getting into the territory of "nested fragments", although I'm not sure...
A workaround here is to delay the creation of the navigator in the onStart
method by scheduling the creation to run on the UI thread at a slightly later date. It's not great, but it's all I've been able to find.
To be clear: This seems to be caused by the BottomNavigator eagerly instantiating and adding Fragments when the Fragment containing it is in the middle of being added. Delaying it allows the instantiation to happen after the Fragment transaction has completed.
Any chance you could create a minimal project that demonstrates the bug?