Jetpack Navigation zu Navigation Compose migrieren

Mit der Navigation Compose API können Sie in einer Composer-Anwendung zwischen zusammensetzbaren Funktionen wechseln und dabei die Komponente, die Infrastruktur und die Funktionen der Jetpack Navigation-Komponente nutzen.

Auf dieser Seite wird beschrieben, wie Sie im Rahmen der größeren, ansichtsbasierten UI-Migration zu Jetpack Compose von einer fragmentbasierten Jetpack-Navigation zu „Navigation Compose“ migrieren.

Voraussetzungen für die Migration

Sie können zu „Navigation Compose“ migrieren, sobald Sie alle Ihre Fragmente durch entsprechende zusammensetzbare Funktionen für den Bildschirm ersetzen können. Zusammensetzbare Funktionen für Bildschirme können eine Mischung aus „Schreiben“ und „Inhalt ansehen“ enthalten. Alle Navigationsziele müssen jedoch zusammensetzbare Funktionen sein, damit die Migration der Funktion „Schreibassistent“ aktiviert werden kann. Bis dahin sollten Sie in der Interop-Codebasis View und Composer weiter die Fragmentbasierte Navigation-Komponente verwenden. Weitere Informationen finden Sie in der Dokumentation zur Navigation Interop.

Die Verwendung der Funktion „Navigationserstellung“ in einer App, die nur zum Schreiben verwendet wird, ist keine Voraussetzung. Sie können weiterhin die Fragmentbasierte Navigationskomponente verwenden, solange Sie Fragmente zum Hosten Ihrer zusammensetzbaren Inhalte behalten.

Migrationsschritte

Unabhängig davon, ob Sie unserer empfohlenen Migrationsstrategie folgen oder einen anderen Ansatz wählen, werden Sie an einem Punkt erreicht, an dem alle Navigationsziele zusammensetzbare Bildschirme sind, wobei Fragmente nur als zusammensetzbare Container dienen. In dieser Phase können Sie zu Navigation Compose migrieren.

Wenn Ihre Anwendung bereits einem UDF-Designmuster und unserem Leitfaden zur Architektur folgt, sollten für die Migration zu Jetpack Compose und Navigation Compose außer der UI-Ebene keine größeren Refaktorierungen anderer Ebenen Ihrer Anwendung erforderlich sind.

So migrieren Sie zu Navigation Compose:

  1. Fügen Sie Ihrer Anwendung die Abhängigkeit zur Erstellung der Navigation hinzu.
  2. Erstellen Sie eine zusammensetzbare Funktion App-level und fügen Sie sie der Activity als Einstiegspunkt für die Erstellung hinzu. Dabei müssen Sie das Layout „Ansicht“ ersetzen:

    class SampleActivity : ComponentActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            // setContentView<ActivitySampleBinding>(this, R.layout.activity_sample)
            setContent {
                SampleApp(/* ... */)
            }
        }
    }

  3. Richten Sie das NavController an einer Stelle ein, an der alle zusammensetzbaren Funktionen, die darauf verweisen müssen, Zugriff darauf haben. Dies befindet sich normalerweise in der zusammensetzbaren Funktion App. Dieser Ansatz folgt den Prinzipien des Zustandszugs und ermöglicht Ihnen, NavController als Quelle für die Navigation zwischen zusammensetzbaren Bildschirmen und die Wartung des Back Stacks zu verwenden:

    @Composable
    fun SampleApp() {
        val navController = rememberNavController()
        // ...
    }

  4. Erstellen Sie das NavHost Ihrer App in der zusammensetzbaren Funktion der App und übergeben Sie navController:

    @Composable
    fun SampleApp() {
        val navController = rememberNavController()
    
        SampleNavHost(navController = navController)
    }
    
    @Composable
    fun SampleNavHost(
        navController: NavHostController
    ) {
        NavHost(navController = navController, startDestination = "first") {
            // ...
        }
    }

  5. Fügen Sie die composable-Ziele hinzu, um das Navigationsdiagramm zu erstellen. Wenn jeder Bildschirm bereits zu „Compose“ migriert wurde, werden bei diesem Schritt nur diese zusammensetzbaren Bildschirmkomponenten aus den Fragmenten in die composable-Ziele extrahiert:

    class FirstFragment : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View {
            return ComposeView(requireContext()).apply {
                setContent {
                    // FirstScreen(...) EXTRACT FROM HERE
                }
            }
        }
    }
    
    @Composable
    fun SampleNavHost(
        navController: NavHostController
    ) {
        NavHost(navController = navController, startDestination = "first") {
            composable("first") {
                FirstScreen(/* ... */) // EXTRACT TO HERE
            }
            composable("second") {
                SecondScreen(/* ... */)
            }
            // ...
        }
    }

  6. Wenn Sie die Anleitung zum Erstellen der UI für die Erstellung von Berichten befolgt haben, insbesondere wie ViewModels und Navigationsereignisse an zusammensetzbare Funktionen übergeben werden sollen, müssen Sie im nächsten Schritt ändern, wie Sie die ViewModel für jede zusammensetzbare Funktion festlegen. Sie können die Hilt-Injektion und ihren Integrationspunkt mit „Compose“ und „Navigation“ über hiltViewModel häufig verwenden:

    @Composable
    fun FirstScreen(
        // viewModel: FirstViewModel = viewModel(),
        viewModel: FirstViewModel = hiltViewModel(),
        onButtonClick: () -> Unit = {},
    ) {
        // ...
    }

  7. Ersetzen Sie alle findNavController()-Navigationsaufrufe durch die navController und übergeben Sie diese als Navigationsereignisse an die einzelnen zusammensetzbaren Bildschirme, anstatt den gesamten navController-Code zu übergeben. Dieser Ansatz folgt den Best Practices zur Freigabe von Ereignissen aus zusammensetzbaren Funktionen für Aufrufer und behält navController als zentrale Datenquelle bei.

    1. Wenn Sie zuvor das Safe Args-Plug-in zum Generieren von Navigationsrichtungen und -aktionen verwendet haben, ersetzen Sie es durch route. Das ist ein Stringpfad zu Ihrer zusammensetzbaren Funktion, der für jedes Ziel eindeutig ist.
    2. Informationen zum Ersetzen von sicheren Argumenten beim Übergeben von Daten finden Sie unter Mit Argumenten navigieren.
    3. Informationen zur Typensicherheit in Navigation Compose finden Sie unten im Abschnitt „Sichere Args“.

      @Composable
      fun SampleNavHost(
          navController: NavHostController
      ) {
          NavHost(navController = navController, startDestination = "first") {
              composable("first") {
                  FirstScreen(
                      onButtonClick = {
                          // findNavController().navigate(firstScreenToSecondScreenAction)
                          navController.navigate("second_screen_route")
                      }
                  )
              }
              composable("second") {
                  SecondScreen(
                      onIconClick = {
                          // findNavController().navigate(secondScreenToThirdScreenAction)
                          navController.navigate("third_screen_route")
                      }
                  )
              }
              // ...
          }
      }

  8. Entfernen Sie alle Fragmente, relevanten XML-Layouts, unnötige Navigation und andere Ressourcen sowie veraltete Fragment- und Jetpack-Navigationsabhängigkeiten.

Die gleichen Schritte mit weiteren Details zu Navigation Compose finden Sie in der Dokumentation zur Einrichtung.

Gängige Anwendungsfälle

Unabhängig von der verwendeten Navigationskomponente gelten dieselben Prinzipien wie bei der Navigation.

Zu den häufigsten Anwendungsfällen bei der Migration gehören:

Weitere Informationen zu diesen Anwendungsfällen finden Sie unter Mit Composer navigieren.

Safe Args

Im Gegensatz zu Jetpack Navigation unterstützt Navigation Compose die Verwendung des SafeArgs-Plug-ins zur Codegenerierung nicht. Stattdessen können Sie die Typsicherheit mit Navigation Compose erreichen, indem Sie Ihren Code so strukturieren, dass er während der Laufzeit typsicher ist.

Komplexe Daten beim Navigieren abrufen

Die Funktion „Navigation Compose“ ist routenbasiert und unterstützt im Gegensatz zu Jetpack Navigation nicht die Übergabe benutzerdefinierter Parcelables und Serializables als Argumente.

Wir raten dringend davon ab, komplexe Datenobjekte beim Navigieren zu umgehen. Übergeben Sie stattdessen bei der Durchführung von Navigationsaktionen die unbedingt notwendigen Informationen wie eine eindeutige Kennung oder eine andere Art von ID als Argumente. Sie sollten komplexe Objekte als Daten in einer einzigen verlässlichen Quelle speichern, z. B. in der Datenebene. Weitere Informationen finden Sie unter Komplexe Daten während der Navigation abrufen.

Wenn Ihre Fragmente komplexe Objekte als Argumente übergeben, sollten Sie Ihren Code zuerst so refaktorieren, dass diese Objekte gespeichert und aus der Datenschicht abgerufen werden können. Beispiele findest du im Repository von Now in Android.

Einschränkungen

In diesem Abschnitt werden die aktuellen Einschränkungen für die Funktion „Navigation Compose“ beschrieben.

Inkrementelle Migration zu Navigation Compose

Derzeit können Sie „Navigation Compose“ nicht verwenden, während Sie in Ihrem Code weiterhin Fragmente als Ziele verwenden. Damit Sie „Navigation Compose“ verwenden können, müssen alle Ziele zusammensetzbare Funktionen sein. Sie können diese Funktionsanfrage im Issue Tracker verfolgen.

Übergangsanimationen

Ab Navigation 2.7.0-alpha01 wird die Einstellung von benutzerdefinierten Übergängen (früher von AnimatedNavHost) jetzt direkt in NavHost unterstützt. Weitere Informationen finden Sie in den Versionshinweisen.

Weitere Informationen

Weitere Informationen zur Migration zu Navigation Compose finden Sie in den folgenden Ressourcen:

  • Codelab zur Navigation Compose: In einem praxisorientierten Codelab lernen Sie die Grundlagen von Navigation Compose.
  • Now in Android Repository: Eine voll funktionsfähige Android-App, die vollständig mit Kotlin und Jetpack Compose erstellt wurde und die Best Practices für Design und Entwicklung von Android umsetzt und Navigation Compose enthält.
  • Migration von Sunflower zu Jetpack Compose: In diesem Blogpost wird der Migrationsprozess der Sunflower-Beispielanwendung von Views zu Jetpack Compose dokumentiert, der auch die Migration zu Navigation Compose umfasst.
  • Jetnews for jeden Bildschirm: Ein Blogpost, in dem die Refaktorierung und Migration des Jetnews-Beispiels dokumentiert wird, damit alle Bildschirme mit Jetpack Compose und Navigation Compose unterstützt werden.