Navigation Component and multi backstack navigation

You are now in the fourth part of a great article about Navigation Component in a multi-module project. If you already know:





Then welcome to the final part of the story about my experience with this wonderful library - about the solution for iOS-like multistack navigation.





You can see how it all works here





If you do not know, then go out and come in normally read the three articles above first.





In addition to the Navigation Component library, Google has released several frontend add-ons called NavigationUI to help you connect navigation to BottomBar, Menu, and other standard components. But often there are requirements that each tab has its own stack and the current states are preserved when switching between them. Unfortunately, out of the box, Navigation Component and NavigationUI don't do that.





Support for this approach was provided by Google themselves in their architecture-components-samples repository on GitHub ( https://github.com/android/architecture-components-samples/tree/master/NavigationAdvancedSample ). Its essence is simple:









  1. Add FragmentContainer.





  2. NavHostFragment .





  3. NavHostFragment FragmentManager-a.





, :





  • sign in / up flow, on boarding , , . , , .





  • . NavigationBottomBar Deep Link-. , deep link- . ,  —  . NavigationExtensions 250 loc, lazy- NavHost-, :





/ NavHost-:





fun obtainNavHostFragment(    
    fragmentManager: FragmentManager,    
    fragmentTag: String,    
    navGraphId: Int,    
    containerId: Int
): NavHostFragment {    
    // If the Nav Host fragment exists, return it    
    val existingFragment =    
    fragmentManager.findFragmentByTag(fragmentTag) as NavHostFragment?    
    existingFragment?.let { return it }    
    // Otherwise, create it and return it.    
    val navHostFragment = NavHostFragment.create(navGraphId)    
    fragmentManager.beginTransaction()        
        .add(containerId, navHostFragment, fragmentTag)        
        .commitNow()    
    return navHostFragment
}
      
      



NavHost-:





protected fun selectTab(tab: Tab) {    
    val newFragment = obtainNavHostFragment(        
        childFragmentManager,        
        getFragmentTag(tabs.indexOf(tab)),        
        tab.graphId,        
        containerId    
     )    
     val fTrans = childFragmentManager.beginTransaction()    
     with(fTrans) {        
          if (selectedFragment != null) detach(selectedFragment!!)        
          attach(newFragment)       
          commitNow()    
     }    
     selectedFragment = newFragment    
     currentNavController = selectedFragment!!.navController    
     tabSelected(tab)
}
      
      



“Back”:





activity?.onBackPressedDispatcher?.addCallback(    
     viewLifecycleOwner,    
     object: OnBackPressedCallback(true){        
          override fun handleOnBackPressed() {            
               val isNavigatedUp = currentNavController.navigateUp()            
               if(isNavigatedUp){                
                    return            
               }else{                
                    activity?.finish()            
               }        
          }    
     }
)
      
      



iOS-like , lazy- .  —  , .








All Articles