Mit der Navigation Compose API können Sie in einer Compose-App zwischen Komponenten wechseln und dabei die Komponente, die Infrastruktur und die Funktionen von Jetpack Navigation nutzen.
Auf dieser Seite wird beschrieben, wie Sie im Rahmen der größeren Migration der ansichtenbasierten Benutzeroberfläche 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 Fragmente durch entsprechende zusammensetzbare Bildschirmelemente ersetzen konnten. Bildschirm-Composeables können eine Mischung aus Compose- und Ansichtsinhalten enthalten. Alle Navigationsziele müssen jedoch Composeables sein, damit die Migration von Navigations-Composes möglich ist. Bis dahin sollten Sie die fragmentbasierte Navigationskomponente in Ihrer Interoperabilitätsansicht und Compose-Codebasis weiterhin verwenden. Weitere Informationen finden Sie in der Dokumentation zur Navigationsinteroperabilität.
Die Verwendung von Navigation Compose in einer reinen Compose-App ist keine Voraussetzung. Sie können die fragmentbasierte Navigationskomponente weiterhin verwenden, solange Sie Fragmente zum Hosten Ihrer zusammensetzbaren Inhalte beibehalten.
Migrationsschritte
Unabhängig davon, ob Sie unserer empfohlenen Migrationsstrategie folgen oder einen anderen Ansatz verfolgen, werden Sie irgendwann an den Punkt kommen, an dem alle Navigationsziele Screen Composeables sind und Fragmente nur als Composeable-Container dienen. In dieser Phase können Sie zu Navigation Compose migrieren.
Wenn Ihre App bereits einem UDF-Designmuster und unserem Leitfaden zur Architektur folgt, sollte die Migration zu Jetpack Compose und Navigation Compose abgesehen von der UI-Ebene keine größeren Refactorings anderer Schichten Ihrer App erfordern.
So migrieren Sie zu Navigation Compose:
- Fügen Sie Ihrer App die Navigation Compose-Abhängigkeit hinzu.
Erstellen Sie eine zusammensetzbare Funktion
App-level
und fügen Sie sie demActivity
als Einstiegspunkt zum Schreiben hinzu. Dadurch wird die Einrichtung des Layouts „View“ ersetzt:class SampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // setContentView<ActivitySampleBinding>(this, R.layout.activity_sample) setContent { SampleApp(/* ... */) } } }
Erstellen Sie Typen für jedes Navigationsziel. Verwenden Sie
data object
für Ziele, für die keine Daten erforderlich sind, unddata class
oderclass
für Ziele, für die Daten erforderlich sind.@Serializable data object First @Serializable data class Second(val id: String) @Serializable data object Third
Platzieren Sie
NavController
an einem Ort, an dem alle zusammensetzbaren Funktionen, die darauf verweisen müssen, Zugriff darauf haben. Das befindet sich normalerweise innerhalb der zusammensetzbaren DateiApp
. Dieser Ansatz folgt den Grundsätzen des Zustands-Hoisting und ermöglicht es,NavController
als vertrauenswürdige Quelle für die Navigation zwischen zusammensetzbaren Bildschirmen und die Aufrechterhaltung des Backstacks zu verwenden:@Composable fun SampleApp() { val navController = rememberNavController() // ... }
Erstelle das
NavHost
deiner App in der zusammensetzbarenApp
-Funktion und übergib dasnavController
:@Composable fun SampleApp() { val navController = rememberNavController() SampleNavHost(navController = navController) } @Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { // ... } }
Fügen Sie die
composable
Ziele hinzu, um Ihren Navigationsgraphen zu erstellen. Wenn jeder Bildschirm zuvor zu „Schreiben“ migriert wurde, besteht dieser Schritt nur darin, diese zusammensetzbaren Funktionen aus Ihren Fragmenten in diecomposable
-Ziele zu extrahieren: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(/* ... */) } // ... } }
Wenn Sie der Anleitung zum Entwerfen der Compose-Benutzeroberfläche gefolgt sind, insbesondere dazu, wie
ViewModel
s und Navigationsereignisse an Composables übergeben werden sollten, müssen Sie im nächsten Schritt ändern, wie Sie dieViewModel
für jedes Bildschirm-Composeable bereitstellen. Sie können die Hilt-Injection und den Integrationspunkt mit Compose und Navigation überhiltViewModel
häufig verwenden:@Composable fun FirstScreen( // viewModel: FirstViewModel = viewModel(), viewModel: FirstViewModel = hiltViewModel(), onButtonClick: () -> Unit = {}, ) { // ... }
Ersetzen Sie alle
findNavController()
-Navigationsaufrufe durch dienavController
und übergeben Sie diese als Navigationsereignisse an jeden zusammensetzbaren Bildschirm, anstatt das gesamtenavController
zu übergeben. Dieser Ansatz folgt den Best Practices, Ereignisse aus kombinierbaren Funktionen für Aufrufer freizugeben, und behält dienavController
als Single Source of Truth bei.Daten können an ein Ziel übergeben werden, indem eine Instanz der für dieses Ziel definierten Routenklasse erstellt wird. Sie kann dann entweder direkt aus dem Backstack-Eintrag am Ziel oder über ein
ViewModel
mitSavedStateHandle.toRoute()
abgerufen werden.@Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { composable<First> { FirstScreen( onButtonClick = { // findNavController().navigate(firstScreenToSecondScreenAction) navController.navigate(Second(id = "ABC")) } ) } composable<Second> { backStackEntry -> val secondRoute = backStackEntry.toRoute<Second>() SecondScreen( id = secondRoute.id, onIconClick = { // findNavController().navigate(secondScreenToThirdScreenAction) navController.navigate(Third) } ) } // ... } }
Entfernen Sie alle Fragmente, relevante XML-Layouts, unnötige Navigationselemente und andere Ressourcen sowie veraltete Fragment- und Jetpack Navigation-Abhängigkeiten.
Dieselben Schritte mit weiteren Details zu Navigation Compose finden Sie in der Einrichtungsdokumentation.
Gängige Anwendungsfälle
Unabhängig davon, welche Navigationskomponente Sie verwenden, gelten dieselben Navigationsprinzipien.
Gängige Anwendungsfälle für die Migration:
- Zu einem Composeable wechseln
- Mit Argumenten navigieren
- Deep links
- Verschachtelte Navigation
- Einbindung in die untere Navigationsleiste
- Integration mit einer benutzerdefinierten Navigationskomponente
Weitere Informationen zu diesen Anwendungsfällen finden Sie unter Mit Compose navigieren.
Komplexe Daten bei der Navigation abrufen
Wir empfehlen dringend, bei der Navigation keine komplexen Datenobjekte zu übergeben. Geben Sie stattdessen die minimal erforderlichen Informationen, z. B. eine eindeutige Kennung oder eine andere Art von ID, als Argumente an, wenn Sie Navigationsaktionen ausführen. Komplexe Objekte sollten als Daten in einer einzigen zentralen Informationsquelle gespeichert werden, z. B. in der Datenebene. Weitere Informationen finden Sie unter Abrufen komplexer Daten beim Navigieren.
Wenn Ihre Fragmente komplexe Objekte als Argumente übergeben, sollten Sie Ihren Code zuerst so umstrukturieren, dass diese Objekte in der Datenebene gespeichert und abgerufen werden können. Beispiele finden Sie im Repository „Jetzt bei Android“.
Beschränkungen
In diesem Abschnitt werden die aktuellen Einschränkungen für „Navigation Compose“ beschrieben.
Inkrementelle Migration zu Navigation Compose
Derzeit können Sie Navigation Compose nicht verwenden, wenn Sie in Ihrem Code weiterhin Fragmente als Ziele verwenden. Damit Sie Navigation Compose verwenden können, müssen alle Ziele Composables sein. Sie können die Funktionsanfrage in der Problemverfolgung einsehen.
Übergangsanimationen
Ab Navigation 2.7.0-alpha01 wird die Einstellung benutzerdefinierter Übergänge, die bisher über AnimatedNavHost
erfolgte, 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 zu Navigation Compose: In diesem Codelab lernen Sie die Grundlagen von Navigation Compose kennen.
- Jetzt im Android-Repository: Eine voll funktionsfähige Android-App, die vollständig mit Kotlin und Jetpack Compose entwickelt wurde, die den Best Practices für Android-Design und -Entwicklung folgt und Navigation Compose enthält.
- Sunflower zu Jetpack Compose migrieren: In diesem Blogpost wird die Migration der Beispiel-App „Sunflower“ von Views zu Compose dokumentiert, einschließlich der Migration zu Navigation Compose.
- Jetnews for eachscreen: Ein Blogpost, der die Refaktorierung und Migration des Jetnews-Beispiels dokumentiert, um alle Bildschirme mit Jetpack Compose und Navigation Compose zu unterstützen.
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Mit Compose navigieren
- Compose und andere Bibliotheken
- Weitere Hinweise