<androidx.fragment.app.FragmentContainerView> vs <фрагмент> как представление для NavHost

9

При использовании androidx.fragment.app.FragmentContainerViewв качестве navHost вместо обычного fragmentприложения не удается перейти к месту назначения после изменения ориентации.

Я получаю следующую ошибку: java.lang.IllegalStateException: no current navigation node

Есть ли что-то, что я должен знать о том, как правильно его использовать, или мой способ использования компонентов Nav неверен?

Простое упражнение xml с видом:


...
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        app:navGraph="@navigation/nav_simple" />
...

Навигационный код:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_legislator.xml"
    app:startDestination="@id/initialFragment">

    <fragment
        android:id="@+id/initialFragment"
        android:name="com.example.fragmenttag.InitialFragment"
        android:label="Initial Fragment"
        tools:layout="@layout/initial_fragment">
        <action
            android:id="@+id/action_initialFragment_to_destinationFragment"
            app:destination="@id/destinationFragment" />
    </fragment>
    <fragment
        android:id="@+id/destinationFragment"
        android:name="com.example.fragmenttag.DestinationFragment"
        android:label="Destination Fragment"
        tools:layout="@layout/destination_fragment" />

</navigation>

Вот репозиторий Github, где вы можете легко воспроизвести ошибку: https://github.com/dmytroKarataiev/navHostBug

Дмитрий Каратаев
источник
Вы должны положить <fragmentв FragmentContainerView.
EpicPandaForce

Ответы:

18

no current navigation nodeОшибка возникает , когда нет установленного графика , и вы пытаетесь вызвать navigate(). Если это происходит только при использовании FragmentContainerViewи после изменения конфигурации, то это будет связано с этой ошибкой , которая исправлена ​​и запланирована к выпуску с помощью Navigation 2.2.0-rc03.

Чтобы обойти эту проблему, вы можете либо переключиться обратно <fragment>или удалить app:navGraph="@navigation/nav_simple"и вместо этого позвонить navController.setGraph(R.navigation.nav_simple).

ianhanniballake
источник
Я действительно попробовал этот подход, и я получил точно такую ​​же ошибку. Сможете ли вы проверить репо и попытаться заставить его работать с этим подходом?
Дмитрий Каратаев
Также этот сбой происходит только после изменения ориентации. Это работает все остальные времена.
Дмитрий Каратаев
Я на самом деле думаю, что это не та же ошибка, навигационный контроллер не равен нулю в моем вопросе, но его задний стек пуст, а график пуст.
Дмитрий Каратаев
Ах, да, это довольно важная информация. Похоже, что вы испытываете это другая проблема . Я обновил свой ответ, чтобы обсудить, что происходит в этом вопросе.
ianhanniballake
Спасибо, отлично.
Дмитрий Каратаев
0

Я не вижу никакого объяснения, почему заменить Fragment view FragmentContainerView . Вот почему добавьте этот ответ:

Одним из распространенных шаблонов размещения фрагментов в деятельности является использование FrameLayout. Сообщество Android делает это годами, но сейчас это изменится. Команда androidx представила это новое представление FragmentContainerView, чтобы сделать это для вас.

Все, что вам нужно сделать, это заменить свой FrameLayout на FragmentContainerView, и все должно работать «из коробки», вам не нужно ничего менять при обработке транзакций фрагментов.

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

Если вы спрашиваете, может ли этот тег заменить? тогда ответ - да. Все, что вам нужно сделать, это добавить android: name = "your_class_name" при определении FragmentContainerView, и он будет использовать FragmentTransaction для создания и показа вашего фрагмента. Это означает, что вы можете использовать транзакции фрагмента позже, чтобы заменить его.

Источник

Документы для Android

Michalsx
источник
1
Я не верю, что это отвечает на вопрос, который задавал автор.
AlgoRyan
Это все еще хорошая дополнительная информация.
Rvb84