<androidx.fragment.app.FragmentContainerView> vs <fragment> jako widok dla NavHost

9

Podczas używania androidx.fragment.app.FragmentContainerViewjako navHost zamiast zwykłej fragmentaplikacji nie można nawigować do miejsca docelowego po zmianie orientacji.

Otrzymuję następujący błąd: java.lang.IllegalStateException: no current navigation node

Czy jest jakiś problem, który powinienem wiedzieć, aby go poprawnie używać, czy też mój sposób używania komponentów nav jest nieprawidłowy?

Proste działanie xml z widokiem:


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

Kod nawigacyjny:

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

Oto repozytorium github, w którym można łatwo odtworzyć błąd: https://github.com/dmytroKarataiev/navHostBug

Dmytro Karataiew
źródło
Musisz umieścić <fragmentw FragmentContainerView.
EpicPandaForce

Odpowiedzi:

18

no current navigation nodeBłąd występuje, gdy nie ma zestaw wykres i spróbujesz zadzwonić navigate(). Jeśli wystąpi to tylko podczas używania FragmentContainerViewi po zmianie konfiguracji, będzie to związane z tym błędem , który został naprawiony i zaplanowany do wydania w Nawigacji 2.2.0-rc03.

Aby obejść ten problem, możesz albo przełączyć się z powrotem, <fragment>albo usunąć, app:navGraph="@navigation/nav_simple"i zamiast tego zadzwonić navController.setGraph(R.navigation.nav_simple).

ianhanniballake
źródło
W rzeczywistości wypróbowałem to podejście i otrzymałem dokładnie ten sam błąd. Czy byłbyś w stanie sprawdzić repozytorium i spróbować, aby działało z tym podejściem?
Dmytro Karataiev,
Ponadto ta awaria występuje tylko po zmianie orientacji. Działa cały czas.
Dmytro Karataiev,
Właściwie myślę, że to nie ten sam błąd, kontroler nawigacyjny nie ma wartości null w moim pytaniu, ale jego tylny stos jest pusty, a wykres jest zerowy.
Dmytro Karataiev,
Ach, tak, to całkiem ważna informacja. Wygląda na to, że to, czego doświadczasz, to ten drugi problem . Zaktualizowałem swoją odpowiedź, aby omówić, co się dzieje w tym numerze.
ianhanniballake
Dziękuję idealnie.
Dmytro Karatajew
0

Nie widzę żadnego wyjaśnienia dlaczego zastąpić Fragment widok z FragmentContainerView . Dlatego dodaj tę odpowiedź:

Jednym z typowych wzorców hostowania fragmentów w działaniu jest użycie FrameLayout. Społeczność Androida robi to od lat, ale teraz to się zmieni. Zespół Androidx wprowadził nowy widok o nazwie FragmentContainerView, aby zrobić to za Ciebie.

Wszystko, co musisz zrobić, to zastąpić FrameLayout FragmentContainerView i wszystko powinno działać od razu, nie musisz nic zmieniać w sposobie obsługi transakcji fragmentów.

Korzyści, jakie tu uzyskano, to poprawiona obsługa tak zwanej kolejności Z dla fragmentów. Oto przykład, którego użyli, ale w zasadzie oznacza to na przykład, że wyjście i przejście między dwoma fragmentami nie będą się na siebie nakładać. Zamiast tego FragmentContainerView rozpocznie animację wyjściową, a następnie animację wejściową.

Jeśli pytasz, czy to może zastąpić tag? wtedy odpowiedź brzmi tak. Wszystko, co musisz zrobić, to dodać Androida: name = "twoja_klasa_nazwa" podczas definiowania FragmentContainerView i użyje FragmentTransaction pod maską do zbudowania i pokazania twojego fragmentu. Oznacza to, że możesz później użyć transakcji fragmentów, aby je zastąpić.

Źródło

Dokumenty na Androida

Michalsx
źródło
1
Nie wierzę, że to odpowiada na pytanie, które zadał autor.
AlgoRyan
To wciąż dobra dodatkowa informacja.
Rvb84