Reputation: 53
I'm testing this new library out and want to navigate to a login fragment if the user isn't signed in. This check is done in in a base fragment like:
abstract class SignedInFragment : Fragment() {
override fun onResume() {
super.onResume()
if (FirebaseAuth.getInstance().currentUser == null) {
NavHostFragment.findNavController(this /* Fragment */)
.navigate(R.id.action_login)
}
}
}
But this just ends up in a RuntimeException saying FragmentManager is already executing transactions:
java.lang.RuntimeException: Unable to resume activity {me.hammarstrom.loco/me.hammarstrom.loco.MainActivity}: java.lang.IllegalStateException: FragmentManager is already executing transactions
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3645)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3685)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2898)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
The navigation graph looks as following:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@id/mainFragment">
<fragment
android:id="@+id/loginFragment"
android:name="me.hammarstrom.loco.ui.login.LoginFragment"
android:label="LoginFragment" >
<action
android:id="@+id/action_loginFragment_to_signedInFragment"
app:destination="@id/signedInFragment" />
</fragment>
<fragment
android:id="@+id/signedInFragment"
android:name="me.hammarstrom.loco.ui.common.SignedInFragment"
android:label="SignedInFragment" />
<fragment
android:id="@+id/mainFragment"
android:name="me.hammarstrom.loco.ui.main.MainFragment"
android:label="MainFragment" />
<action
android:id="@+id/action_login"
app:destination="@id/loginFragment" />
Should this kind of navigation be done in some other way? Am I missing something?
Upvotes: 5
Views: 2895
Reputation: 3035
Looks like a bug in Android Architecture Components. I created a bug report regarding this issue here. I've found that temporary workaround for it is to delay the call to the navigation method so that the fragment manager can execute pending transactions.
val executor = Executors.newSingleThreadScheduledExecutor()
executor.schedule({
activity?.runOnUiThread { NavHostFragment.findNavController(this)
.navigate(R.id.action_login) }
}, 1, TimeUnit.MILLISECONDS)
or if you are using coroutines
launch(UI) {
delay(1L)
NavHostFragment.findNavController(this).navigate(R.id.action_login)
}
UPDATE:
This issue has been fixed in version 1.0.0-alpha02
.
Upvotes: 7
Reputation: 24907
This issue has been fixed in Navigation 1.0.0-alpha02
. Based on release notes:
Fixed an IllegalStateException when calling navigate from Fragment lifecycle methods
Upvotes: 1