Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Navigating with Compose in multi-module code

Adit Lal
November 14, 2022

Navigating with Compose in multi-module code

This talk would be targeting a vital and a pressing matter - how does one navigate to
composable screens using Android Navigation for compose in a multi-modular code architecture, where feature screens are written in feature modules. Problems faced and how to overcome them. We would be discussing some key learning points to remember while navigating between screens

Adit Lal

November 14, 2022
Tweet

More Decks by Adit Lal

Other Decks in Programming

Transcript

  1. Large amount of mobile apps need some form of navigation

    When working with compostable , is it possible to navigate between them? In Compose world - fragment free , preferably single Activity. Navigating in apps
  2. Jetpack Navigation 2019 Navigation Graph Navigation Intent 2008 Activity based

    navigation Fragment Manager 2011 Fragment based navigation
  3. NavHost( navController = navController, startDestination = Screen.List.route ){ composable(“Details”) {

    DetailsScreen(...) } composable(“Search”) { SearchScreen(...) } composable(“List”) { ListScreen(...) } } NavHost Destination Destination Destination Compose + Navigation
  4. NavHost( navController = navController, startDestination = Screen.List.route ){ composable(“Details”) {

    DetailsScreen(...) } composable(“Search”) { SearchScreen(...) } composable(“List”) { ListScreen(...) } } NavHost Destination Destination Destination Compose + Navigation
  5. NavHost( navController = navController, startDestination = Screen.List.route ){ composable(“Details”) {

    DetailsScreen(...) } composable(“Search”) { SearchScreen(...) } composable(“List”) { ListScreen(...) } } NavHost Destination Destination Destination Compose + Navigation
  6. How to Navigate to Composables across di ff erent features

    modules without depending on a NavHostController reference
  7. How to decouple these modules from Compose Navigation and handle

    navigation in a centralised location through View Models
  8. How to provide View Models to these Composables using Hilt

    Navigation Compose without having each feature module rely on that dependency
  9. Navigation Manager Navigation Commands Hilt Navigation Compose Activity Compose Nav

    Controller uses uses uses observes declares App module Nav module
  10. Navigation Manager Navigation Commands Hilt Navigation Compose Activity ViewModel Compose

    Nav Controller Composable provides uses uses uses uses uses triggers observes declares navigates to App module Nav module Feature module
  11. @Composable fun StarWarsPeopleList( viewModel: PeopleListViewModel ) { val state by

    viewModel.uiState.observeAsState() StarWarsPeopleList(state) }
  12. @Composable fun StarWarsPeopleList( viewModel: PeopleListViewModel ) { val state by

    viewModel.uiState.observeAsState() StarWarsPeopleList(state) }
  13. @Composable fun StarWarsPeopleList( viewModel: PeopleListViewModel ) { val state by

    viewModel.uiState.observeAsState() StarWarsPeopleList(state) }
  14. @Composable fun StarWarsPeopleList( viewModel: PeopleListViewModel ) { val state by

    viewModel.uiState.observeAsState() StarWarsPeopleList(state) }
  15. @Composable fun Details( viewModel: DetailsViewModel ) { val state by

    viewModel.uiState.observeAsState() DetailsContent(state) } @HiltViewModel class DetailsViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle, ... ) : ViewModel()
  16. @Composable fun Details( viewModel: DetailsViewModel ) { val state by

    viewModel.uiState.observeAsState() DetailsContent(state) } @HiltViewModel class DetailsViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle, ... ) : ViewModel()
  17. object NavigationDirections { val list = object : NavigationCommand {

    override val arguments = emptyList<NamedNavArgument>() override val destination = "peoplelist" } val details = object : NavigationCommand { override val arguments = emptyList<NamedNavArgument>() override val destination = "details" } }
  18. object NavigationDirections { val list = object : NavigationCommand {

    override val arguments = emptyList<NamedNavArgument>() override val destination = "peoplelist" } val details = object : NavigationCommand { override val arguments = emptyList<NamedNavArgument>() override val destination = "details" } }
  19. object DetailsNavigation { private val KEY_PEOPLE_ID = "peopleId" val route

    = "details/{$KEY_PEOPLE_ID}" val arguments = listOf( navArgument(KEY_PEOPLE_ID) { type = NavType.StringType } ) fun details( peopleId: String? = null ) = object : NavigationCommand { override val arguments = arguments override val destination = "details/$KEY_PEOPLE_ID" } }
  20. object DetailsNavigation { private val KEY_PEOPLE_ID = "peopleId" val route

    = "details/{$KEY_PEOPLE_ID}" val arguments = listOf( navArgument(KEY_PEOPLE_ID) { type = NavType.StringType } ) fun details( peopleId: String? = null ) = object : NavigationCommand { override val arguments = arguments override val destination = "details/$KEY_PEOPLE_ID" } }
  21. Navigation Manager Navigation Commands Hilt Navigation Compose Activity ViewModel Compose

    Nav Controller Composable provides uses uses uses uses uses triggers observes declares navigates to App module Nav module Feature module
  22. Navigation Manager Navigation Commands Hilt Navigation Compose Activity ViewModel Compose

    Nav Controller Composable provides uses uses uses uses uses triggers observes declares navigates to App module Nav module Feature module
  23. Navigation Manager Navigation Commands Hilt Navigation Compose Activity ViewModel Compose

    Nav Controller Composable provides uses uses uses uses uses triggers observes declares navigates to App module Nav module Feature module
  24. Navigation Manager Navigation Commands Hilt Navigation Compose Activity ViewModel Compose

    Nav Controller Composable provides uses uses uses uses uses triggers observes declares navigates to App module Nav module Feature module
  25. A component that is used to output the previously de

    fi ned NavigationCommand events, allowing an external class to observe these events| 
 A function that can be used to trigger these NavigationCommand events, allowing the observer of the above component to handle them Handling Navigation Events
  26. Navigation Manager Navigation Commands Hilt Navigation Compose Activity ViewModel Compose

    Nav Controller Composable provides uses uses uses uses uses triggers observes declares navigates to App module Nav module Feature module
  27. @HiltViewModel class PeopleListViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle, private

    val results: Results, private val sharedPrefs: Preferences, private val navigationManager: NavigationManager )
  28. @HiltViewModel class PeopleListViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle, private

    val results: Results, private val sharedPrefs: Preferences, private val navigationManager: NavigationManager )
  29. We’ve removed the need to pass around a NavHostController to

    our composables Source : 
 www.joebirch.co
  30. Hilt ViewModels in Composables but w/o any direct deps in

    feature modules Source : 
 www.joebirch.co
  31. We’ve centralised our navigation logic and created a contract for

    the things which can be triggered Source : 
 www.joebirch.co
  32. Check out https://github.com/aldefy/Andromeda 
 https://bit.ly/3Nic0JF - Sample catalog app 


    
 Andromeda is an open-source Jetpack Compose design system. A collection of guidelines and components can be used to create amazing compose app user experiences. Foundations introduce Andromeda tokens and principles while Components provide the bolts and nuts that make Andromeda Compose wrapped apps tick.