Не удается получить доступ к фрагменту после его очистки из заднего стека

#android #kotlin

#Android #kotlin

Вопрос:

У меня есть два потока, которые могут произойти в моем приложении: A1-> A2-> B или A1-> B, A и B — разные действия, 1 и 2 разных фрагмента. Когда в B нет причин возвращаться к A2, поэтому я использую следующий код для очистки стека фрагментов перед запуском действия B (startcontrol()) из A2:

 requireFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
(activity as MainActivity?)?.startControle()
 

Проблема в том, что когда я возвращаюсь к A1 и пытаюсь перейти к A2, приложение вылетает

 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.ufrj.projetointegrado, PID: 23181
    java.lang.IllegalArgumentException: Navigation action/destination com.ufrj.projetointegrado:id/action_inicio_to_btOff cannot be found from the current destination Destination(com.ufrj.projetointegrado:id/btOff) label=btOff class=com.ufrj.projetointegrado.btOff
        at androidx.navigation.NavController.navigate(NavController.java:938)
        at androidx.navigation.NavController.navigate(NavController.java:875)
        at androidx.navigation.NavController.navigate(NavController.java:861)
        at androidx.navigation.NavController.navigate(NavController.java:849)
        at com.ufrj.projetointegrado.inicio$onCreateView$1.onClick(inicio.kt:31)
        at android.view.View.performClick(View.java:6600)
        at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)
        at android.view.View.performClickInternal(View.java:6577)
        at android.view.View.access$3100(View.java:781)
        at android.view.View$PerformClick.run(View.java:25917)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:215)
        at android.app.ActivityThread.main(ActivityThread.java:6939)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:870)
 

Кто-нибудь знает, что я делаю не так?

Редактировать

Я также пробовал этот способ, но он ведет себя так же:

 val navController = this.findNavController()
navController.popBackStack(R.id.inicio, true);
(activity as MainActivity?)?.startControle()
 

Комментарии:

1. Почему вы FragmentManager вообще используете напрямую, если используете NavController и его popBackStack() API?

2. @ianhanniballake Я тоже пробовал использовать NavController, просто обновил вопрос.

3. R.id.inicio Ваш startDestination график (ваш ‘A1’ в вашем вопросе)? Вы также хотите открыть A1 (поскольку вы используете inclusive = true)?

4. Да, это так. На самом деле я просто хочу открыть A2.

5. Это было оно! Спасибо @ianhanniballake!

Ответ №1:

Во-первых, при использовании навигации вы всегда должны использовать NavController API-интерфейсы — в частности, использовать navController.popBackStack() , а не FragmentManager напрямую API.

Во-вторых, переход true к popBackStack() означает инклюзивный pop, то есть также pop адресата, который вы передаете. Если вы хотите открыть только A2, находясь на A2, вы могли бы

А) Использовать popBackStack() (который отображает только самый верхний пункт назначения) Б) Использовать popBackStack() с идентификатором A2 и включительно true В) Использовать popBackStack() с идентификатором A1 и включительно false

В-третьих, хотя вызов popBackStack() , а затем вызов startActivity() вручную — это нормально, вы также можете использовать комбинацию popUpTo и назначения действий, чтобы указать пункт назначения и перейти к действию как к одной операции.

 <activity
    android:id="@ id/activity_b"
    android:name="com.example.ActivityB" />
 

Затем добавьте действие для перехода от A2 к B:

 <action
    android:id="@ id/a2_to_b"
    app:popUpTo="@ id/inicio"
    app:destination="@ id/activity_b" />