Компонент архитектуры навигации - невозможно перейти к фрагменту из onResume

Я тестирую эту новую библиотеку и хочу перейти к фрагменту входа в систему, если пользователь не вошел в систему. Эта проверка выполняется в базовом фрагменте, например:

abstract class SignedInFragment : Fragment() {

override fun onResume() {
    super.onResume()
    if (FirebaseAuth.getInstance().currentUser == null) {
        NavHostFragment.findNavController(this /* Fragment */)
                .navigate(R.id.action_login)
    }
}

}

Но это заканчивается исключением RuntimeException, в котором говорится, что FragmentManager уже выполняет транзакции:

    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)

График навигации выглядит следующим образом:

<?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" />

Следует ли делать такую ​​навигацию каким-либо другим способом? Я что-то пропустил?

5
0
2 344
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Похоже на ошибку в компонентах архитектуры Android. Я создал отчет об ошибке по этой проблеме здесь. Я обнаружил, что временный обходной путь заключается в том, чтобы отложить вызов метода навигации, чтобы диспетчер фрагментов мог выполнять ожидающие транзакции.

val executor = Executors.newSingleThreadScheduledExecutor()
executor.schedule({
        activity?.runOnUiThread { NavHostFragment.findNavController(this)
            .navigate(R.id.action_login) }
}, 1, TimeUnit.MILLISECONDS)

или если вы используете сопрограммы

launch(UI) {
    delay(1L)
    NavHostFragment.findNavController(this).navigate(R.id.action_login)
}

Обновлено:

Эта проблема исправлена ​​в версии 1.0.0-alpha02.

Эта проблема исправлена ​​в Navigation 1.0.0-alpha02. На основе примечания к выпуску:

Fixed an IllegalStateException when calling navigate from Fragment lifecycle methods

Другие вопросы по теме