Search code examples
androidandroid-fragmentsandroid-activitynavigation-drawerandroid-navigation

One-Single Activity or Two Activities


My app's main Activity (containing a NavigationDrawer) allows to navigate through many (20 aprox) Fragments, because of navDrawer item clicks and other views' clicks inside each fragment.

Then, it moves to a point where I need a BottomNavigationView (maintaining also the navDrawer). From this point, because of the bottomNavView and other views' clicks, I can move to other different 10-15 fragments, aprox, and also to the ones that the main NavigationDrawer allows, but, in case I move to a Fragment through a click on any main navDrawer's item, the bottomNavView should be hidden.

So, is it correct here to use a One-Single Activity approach and be controlling the visibility of the bottomNavView or shall I use Two Activities in order to avoid being pendent of this in all navigations?


Solution

  • I don't believe there's a "right or wrong" answer in this case.

    It really boils down to how you want to architect your application, as long as you're consistent.

    If your fragments have a "state" and a ViewMOdel and such, then a single activity swapping fragments while controlling its own state (when to show the bottom bar) may be simpler than having to maintain two different activities, since navigation is done always between fragments.

    It will also be tied to how the backstack behaves in each case (so test accordingly to ensure you get the expected behavior).

    Simple Idea (with a single act)

    This is pseudo-code, not perfect, compiling, functional code.

    class BottomBarUseCase() {
       operator fun invoke(destination: String): Boolean =
           when (destination) {
              "A", "B", "C" -> true
              else -> false
           }
    }
    

    Your Activity's ViewModel (greatly simplified of course)

    class XXXViewModel(
       private val bottomBarUseCase: BottomBarUseCase
    ): ViewModel() {
    
        private val _state = MutableLiveData<YourState>(YourState.Empty)
    
        fun setupBottomBar(destination: String) {
           if (bottomBarUseCase(destination)) {
               _state.value = SomeState.ShowBar
           } else {
               _state.value = SomeState.HideBar
           }
        }
    

    Your Activity observes the state and does what it needs to do.

    There are ways to streamline this and what not, but essentially, you're delegating the responsibility to show the bar to the use-Case, which you can test in isolation to ensure it does what you want it to do (aka: don't show the bar for certain destinations).

    Your Fragments don't care about any of this (unless they too, need to make the decision, in which case you can still inject the useCase in the Fragment's viewModels and ask there too, since the useCase doesn't have any special dependency).

    That's what I would do, but without having to do this in real life, it's hard to visualize whether this would have other drawbacks.

    In general, this is how I would approach a problem that needs to be resolved elsewhere in many places: isolating it.

    Hope that clarifies it.