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