This should be the third article of MVVM development framework, the first two can be viewed: Write a MVVM rapid development framework (a) basic class package write a MVVM rapid development framework (b) componentized transformation

Single Activity+ Multiple Fragments Mode

Since I know this, I am not willing to use activities. Fragments can be quickly created and managed, reasonably designed page jumps and cool jump animations, and some operations can be managed uniformly.

  1. Replace activities with fragments

In the past, most of the activities were regarded as pages and fragments as sub-pages in the page (called fragments at that time). Basically, most functions were realized by activities. For example, the old version of Taobao App had hundreds of activities, which were too slow at that time. With technical iteration, we found that activtiy consumes much more performance to create, switch and destroy than Fragment. Fragment can also replace activity to realize most functions now.

  1. Use the Activity as a container

In my understanding, the single Activity+ multiple Fragment mode does not mean that an App must have only one Activity. For some business-related scenarios, it can be integrated into a single Activity+ multiple Fragment module, and the Activity can be used as the Fragment container. Let fragment do the UI painting.

  1. Management of fragments of stack

We can use Navigation to manage fragments, it is easy to manage jumps and stacks between fragments, and navigation can also set switching animations and data transfer between pages.

Navigation components

Navigation is one of the components of Jetpack. IOS used this way of jumping a long time ago. I wondered why Android didn’t, and Navigation came out soon after.

Navigation can be understood as a container for managing fragments. In the container, each fragment can be jumped arbitrarily.

Basic use:

  1. We need to create a Fragment container in the layout:
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/main_fragment_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/nav_main"/>
Copy the code
  1. Create navigation. XML file
<? The XML version = "1.0" encoding = "utf-8"? > <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/navigation_main" app:startDestination="@+id/mainFragment"> <fragment android:id="@+id/mainFragment" android:name="com.example.mvvm_develop.MainFragment" android:label="MainFragment" /> </navigation>Copy the code
  1. Using NavController
val navController = (childFragmentManager.findFragmentById(R.id.module_fragment_container) as NavHostFragment). NavController // Jump navController.navigate(r.i.Copy the code

Some specific parameters and usage:

navGraph

This value points to XML files in which we can define fragment, jump behavior, destination, etc.

Create and add fragments:

Create a jump behavior:

Animation, destination, back stack configuration:

NavController

A NavController can control jumps, returns, animations, listening, etc. We can use it for flexible Navigation, and Google has some Navigation demos showing how to use it with the Toolbar and bottom Navigation bar.

About the specific usage here does not explain, many articles have, can also refer to the official website.

Problems with Navigation:

Retrace the life cycle

Navigation currently has a problem: The problem may be that Google wants the Fragment to work in the same way as the activity. It is really annoying to have a single Fragment life cycle. We can customize navhostFragments to fix this problem

After modification, use the following:

The android: name = "androidx. Navigation. Fragments. NavHostFragment" modify for our custom NavHostFragment:  android:name="com.example.baselibrary.navigation.NavHostFragment" <fragment android:id="@+id/navigation_main" android:name="com.example.baselibrary.navigation.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/nav_main"/>Copy the code

Use Navigation in componentization

We usually use the bottom navigation bar to divide the app into different functions, which are all separate modules, but how to jump between modules in navigation?

Such as:

The layout file is a FragmentContainerView+BottomNavigationView, and switching the buttons below requires switching to a different Moduel page. First we treat different Moduel modules as a single “activity+ multiple fragments” module, or we can omit the activities.

In the Google demo, you create a main_navGraph in the MainActivity, which contains different subModuel navgraphs as follows:

<? The XML version = "1.0" encoding = "utf-8"? > <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_module" app:startDestination="@+id/navi_home"> <include app:graph="@navigation/navi_home"/> <include app:graph="@navigation/navi_collection"/> <include app:graph="@navigation/navi_center"/> </navigation>Copy the code

Navi_home, navi_collection, and navi_center are navGraph files in subModuel, which requires them to specify startDestination and only jump to startDestination

Use with BottomNavigationView:

val navController = (childFragmentManager.findFragmentById(R.id.module_fragment_container) as NavHostFragment).navController
setupWithNavController(binding.bottomNav,navController)
Copy the code

This does allow for switching between Moduel, but I’ve found that naviagtion is reinitialized every time a switch is done, which can be a huge performance drag.

Maybe I’m using the wrong posture?

2. Since the App Module itself relies on sub-Moduel fragments, we can use sub-Moduel fragments directly in navGraph, adding the main Fragment of each Module to the main page:

<? The XML version = "1.0" encoding = "utf-8"? > <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_module" app:startDestination="@+id/navi_home"> <fragment android:id="@+id/navi_home" android:name="com.xlu.module_tab1.HomeFragment" android:label="HomeFragment" /> <fragment android:id="@+id/navi_collection" android:name="com.xlu.module_collection.FragmentCollection" android:label="CenterFragment" /> <fragment android:id="@+id/navi_center" android:name="com.xlu.module_center.CenterFragment" android:label="FragmentCollection" /> </navigation>Copy the code

Switch the Fragment directly when switching the bottom state:

        val navController = (childFragmentManager.findFragmentById(R.id.module_fragment_container) as NavHostFragment).navController

        binding.bottomNav.setOnItemSelectedListener(object :NavigationBarView.OnItemSelectedListener{
            override fun onNavigationItemSelected(item: MenuItem): Boolean {
                navController.navigate(item.itemId)
                return true
            }
        })
Copy the code

If you’re lazy, you can set the ID in the Menu used by the BottomNavigationView to be the same as in navGraph


Basically ARouter+Navigation can handle most of the page Navigation needs, but there are a few challenges, such as how to control each other between different Moduel Navgraphs, which can be implemented by providing interface services as mentioned above. After all, Navigation is not meant to be prepared for componentization.

Finally, attach the mvVM_develop project address, humble Androider online to find a star😅