1. Basic use

Import library

def nav_version = "2.3.2"
// Java language implementation
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
Copy the code

The Activity layout


      
<LinearLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <! App :defaultNavHost="true" -->
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/my_nav_host_fragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="9"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph_main"/>
       
</LinearLayout>
Copy the code

Nav_graph_main.xml in the res/navigation directory


      
<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/nav_graph_main.xml"
    app:startDestination="@id/page1Fragment">
    <fragment
        android:id="@+id/page1Fragment"
        android:name="com.example.lsn4_navigationdemo.MainPage1Fragment"
        android:label="fragment_page1"
        tools:layout="@layout/fragment_main_page1">
            
        <! --action: jump to destination class with id -->
        <action
            android:id="@+id/action_page2"
            app:destination="@id/page2Fragment" />
    </fragment>
                
    <fragment
        android:id="@+id/page2Fragment"
        android:name="com.example.lsn4_navigationdemo.MainPage2Fragment"
        android:label="fragment_page2"
        tools:layout="@layout/fragment_main_page2">
        <action
            android:id="@+id/action_page1"
            app:destination="@id/page1Fragment" />
        <action
            android:id="@+id/action_page3"
            app:destination="@id/page3Fragment" />
    </fragment>

    <! -- <navigation-->
    <! -- android:id="@+id/nav_graph_page3"-->
    <! -- app:startDestination="@id/page3Fragment">-->
    <fragment
        android:id="@+id/page3Fragment"
        android:name="com.example.lsn4_navigationdemo.MainPage3Fragment"
        android:label="fragment_page3"
        tools:layout="@layout/fragment_main_page3"
        >
        <action
            android:id="@+id/action_page2"
            app:destination="@id/page2Fragment"/>
    </fragment>


</navigation>
Copy the code

Fragment calls a jump

// Method 1: Jump to the specified fragment
Navigation.findNavController(view).navigate(R.id.page2Fragment);  

// Mode 2: Action
Navigation.findNavController(view).navigate(R.id.action_page2);   / / jump into page2
Copy the code

Invoke a jump in the Activity

// Obtain controller in method 1
NavController controller=Navigation.findNavController(this,R.id.my_nav_host_fragment);

// Obtain controller in method 2
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.my_nav_host_fragment);
NavController controller = navHostFragment.getNavController();

/ / jump
controller.navigate(R.id.page2Fragment);
Copy the code

The Activity binding navigation

In addition to specifying navigation layout resources in the Activity’s layout, you can also set them through Java code

public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        / / way
        val finalHost = NavHostFragment.create(R.navigation.nav_graph_main)
        supportFragmentManager.beginTransaction()
                .replace(R.id.ll_fragment_navigation, finalHost)
                .setPrimaryNavigationFragment(finalHost)
                .commit();
    }

    2 / / way
    @Override
    public boolean onSupportNavigateUp(a) {
        Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.my_nav_host_fragment);
        returnNavHostFragment.findNavController(fragment).navigateUp(); }}Copy the code

At the bottom of the navigation

Introduces the bottom navigation control

implementation 'com. Google. Android. Material: material: 1.1.0'
Copy the code

layout


      
<LinearLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <! App :defaultNavHost="true" -->
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/my_nav_host_fragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="9"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph_main"/>
        
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/nav_view"
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        app:itemTextColor="#ff0000"
        app:menu="@menu/menu"/>

</LinearLayout>
Copy the code

menu


      
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/page1Fragment"
        android:icon="@drawable/ic_launcher_foreground"
        android:title="1"/>
    <item
        android:id="@+id/page2Fragment"
        android:icon="@drawable/ic_launcher_foreground"
        android:title="2"/>
    <item
        android:id="@+id/page3Fragment"
        android:icon="@drawable/ic_launcher_foreground"
        android:title="3"/>

</menu>
Copy the code

Activity binding navigation

public class MainActivity extends AppCompatActivity {

    BottomNavigationView bottomNavigationView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.action_page1);
        bottomNavigationView=findViewById(R.id.nav_view);
        
        // Obtain controller in method 1
        //NavController controller=Navigation.findNavController(this,R.id.my_nav_host_fragment);
       
        // Obtain controller in method 2
        NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.my_nav_host_fragment);
        NavController controller = navHostFragment.getNavController();
        
        // Bind navigation
        NavigationUI.setupWithNavController(bottomNavigationView,controller);

}
Copy the code

Principle 2.

Initialize the NavHostFragment life cycle method

1. The create – NavHostFragment created

In NavHostFragment. The create method

  1. Initialize the Bundle and store graphResId, startDestinationArgs in the Bundle.
  2. New NavHostFragment() returns the NavHostFragment instance.
    //NavHostFragment.java
    @NonNull
    public static NavHostFragment create(@NavigationRes int graphResId,
            @Nullable Bundle startDestinationArgs) {
        Bundle b = null;
        if(graphResId ! =0) {
            b = new Bundle();
            b.putInt(KEY_GRAPH_ID, graphResId);
        }
        if(startDestinationArgs ! =null) {
            if (b == null) {
                b = new Bundle();
            }
            b.putBundle(KEY_START_DESTINATION_ARGS, startDestinationArgs);
        }

        final NavHostFragment result = new NavHostFragment();
        if(b ! =null) {
            result.setArguments(b);
        }
        return result;
    }
Copy the code

2. OnInflate — parsing of the XML file

The main thing is to resolve the two properties of the layout file, defaultNavHost and navGraph, and initialize the global variables.

NavHostFragment. OnInflate method when fragments, in the form of XML static load, the first is called onInflate method (called time: fragments of the associated Activity when performing the setContentView).

    //NavHostFragment.java
    @CallSuper
    @Override
    public void onInflate(@NonNull Context context, @NonNull AttributeSet attrs,
            @Nullable Bundle savedInstanceState) {
        super.onInflate(context, attrs, savedInstanceState);

        final TypedArray navHost = context.obtainStyledAttributes(attrs,
                androidx.navigation.R.styleable.NavHost);
        final int graphId = navHost.getResourceId(
                androidx.navigation.R.styleable.NavHost_navGraph, 0);
        if(graphId ! =0) {
            mGraphId = graphId;   // Navigation map layout
        }
        navHost.recycle();

        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NavHostFragment);
        final boolean defaultHost = a.getBoolean(R.styleable.NavHostFragment_defaultNavHost, false);
        if (defaultHost) {
            mDefaultNavHost = true;    // Whether to listen for the physical return key
        }
        a.recycle();
    }
Copy the code

3. OnCreateNavController – create the Navigator

When implementing navigation, we need to generate NavGraph class according to navigation configuration file, and then according to each different actionID, find the corresponding NavDestination to realize the page navigation jump.

Create the Navigator

The Navigator class instantiates the corresponding NavDestination, implements navigation, and has its own fallback stack.

    @CallSuper
    protected void onCreateNavController(@NonNull NavController navController) {
        navController.getNavigatorProvider().addNavigator(
                new DialogFragmentNavigator(requireContext(), getChildFragmentManager()));
        
        // Create a Navigator and bind it to NavigatorProvider.
        //mNavigatorProvider is a global variable in NavController that internally holds the Navigator class in the form of HashMap key-value pairs.
        navController.getNavigatorProvider().addNavigator(createFragmentNavigator());
    }
Copy the code
  1. MNavigatorProvider is the global variable in NavController, which internally saves the Navigator class in the form of HashMap key-value pairs
  2. The createFragmentNavigator method builds the FragmentNavigator object, which contains the abstract class Navigator and the important implementation classes ActivityNavigator and NavGraphNavigator. This two-class object is added to the Constructor of the NavController.
//NavController.java
public NavController(@NonNull Context context) {
        mContext = context;
        while (context instanceof ContextWrapper) {
            if (context instanceof Activity) {
                mActivity = (Activity) context;
                break;
            }
            context = ((ContextWrapper) context).getBaseContext();
        }
        mNavigatorProvider.addNavigator(new NavGraphNavigator(mNavigatorProvider));
        mNavigatorProvider.addNavigator(new ActivityNavigator(mContext));
}
Copy the code

4. OnCreate – Navigation initialization

Either the XML implementation or the code implementation executes the Fragment’s onCreate method. The NavController is created here and there is a NavController object in the NavHostFragment.

   @CallSuper
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        final Context context = requireContext();
        
        //1. Initialize NavController. NavController is the core class
        mNavController = new NavHostController(context);
        mNavController.setLifecycleOwner(this); mNavController.setOnBackPressedDispatcher(requireActivity().getOnBackPressedDispatcher()); mNavController.enableOnBackPressed( mIsPrimaryBeforeOnCreate ! =null && mIsPrimaryBeforeOnCreate);
        mIsPrimaryBeforeOnCreate = null;
        mNavController.setViewModelStore(getViewModelStore());
        onCreateNavController(mNavController);

        Bundle navState = null;
        //2. The system starts to recover
        if(savedInstanceState ! =null) {
            navState = savedInstanceState.getBundle(KEY_NAV_CONTROLLER_STATE);
            if (savedInstanceState.getBoolean(KEY_DEFAULT_NAV_HOST, false)) {
                mDefaultNavHost = true;
                getParentFragmentManager().beginTransaction()
                        .setPrimaryNavigationFragment(this)
                        .commit();
            }
            mGraphId = savedInstanceState.getInt(KEY_GRAPH_ID);
        }

        if(navState ! =null) {
            mNavController.restoreState(navState);
        }
        
        //3. Set the navigation chart information
        if(mGraphId ! =0) {
            mNavController.setGraph(mGraphId);
        } else {
            final Bundle args = getArguments();
            final intgraphId = args ! =null ? args.getInt(KEY_GRAPH_ID) : 0;
            finalBundle startDestinationArgs = args ! =null
                    ? args.getBundle(KEY_START_DESTINATION_ARGS)
                    : null;
            if(graphId ! =0) { mNavController.setGraph(graphId, startDestinationArgs); }}super.onCreate(savedInstanceState);
    }
Copy the code

5.onCreateView

The NavHostFragment view has only one FragmentContainerView that inherits FrameLayout

    //NavHostFragment.java
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        FragmentContainerView containerView = new FragmentContainerView(inflater.getContext());
        
        // This line is mainly used to add fragments in code
        containerView.setId(getContainerId());
        return containerView;
    }
Copy the code

6.onViewCreated

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if(! (viewinstanceof ViewGroup)) {
            throw new IllegalStateException("created host view " + view + " is not a ViewGroup");
        }
        // Add the mNavController to the view tag
        Navigation.setViewNavController(view, mNavController);

        if(view.getParent() ! =null) {
            mViewParent = (View) view.getParent();
            if (mViewParent.getId() == getId()) {
                // Add the mNavController to the view tagNavigation.setViewNavController(mViewParent, mNavController); }}}Copy the code

Get NavController

1. Obtain NavController

NavHostFragment.findNavController(fragment)
Copy the code
    //NavHostFragment.java
    @NonNull
    public static NavController findNavController(@NonNull Fragment fragment) {
        Fragment findFragment = fragment;
        while(findFragment ! =null) {
            if (findFragment instanceof NavHostFragment) {
                return ((NavHostFragment) findFragment).getNavController();
            }
            Fragment primaryNavFragment = findFragment.getParentFragmentManager()
                    .getPrimaryNavigationFragment();
            if (primaryNavFragment instanceof NavHostFragment) {
                return ((NavHostFragment) primaryNavFragment).getNavController();
            }
            findFragment = findFragment.getParentFragment();
        }

        View view = fragment.getView();
        if(view ! =null) {
            return Navigation.findNavController(view);
        }
        
        Dialog dialog = fragment instanceof DialogFragment
                ? ((DialogFragment) fragment).getDialog()
                : null;
        if(dialog ! =null&& dialog.getWindow() ! =null) {
            return Navigation.findNavController(dialog.getWindow().getDecorView());
        }

        throw new IllegalStateException("Fragment " + fragment
                + " does not have a NavController set");
    }
Copy the code

2. FindNavController in Navigation

3.findViewNavController

View. Tag to find NavController. The getViewNavController method is called internally.

4.getViewNavController

The getViewNavController method retrieves the NavController object by retrieving the view’s Tag, where the Tag ID and setViewNavController are both nav_controller_view_tag.

    //Navigation.java
    @NonNull
    public static NavController findNavController(@NonNull View view) {
        / / 3.
        NavController navController = findViewNavController(view);
        if (navController == null) {
            throw new IllegalStateException("View " + view + " does not have a NavController set");
        }
        return navController;
    }


     @Nullable
    private static NavController findViewNavController(@NonNull View view) {
        while(view ! =null) {
            NavController controller = getViewNavController(view);
            if(controller ! =null) {
                return controller;
            }
            ViewParent parent = view.getParent();
            view = parent instanceof View ? (View) parent : null;
        }
        return null;
    }

    @Nullable
    private static NavController getViewNavController(@NonNull View view) {
        //4. The tag ID and setViewNavController are both nav_controller_view_tag.
        Object tag = view.getTag(R.id.nav_controller_view_tag);
        NavController controller = null;
        if (tag instanceof WeakReference) {
            controller = ((WeakReference<NavController>) tag).get();
        } else if (tag instanceof NavController) {
            controller = (NavController) tag;
        }
        return controller;
    }
Copy the code

Navigation navigate

navigate

After building and getting the NavController object and the NavGraph. Here’s how to use it for real navigation. Begin the analysis with navigate. NavDestination is queried inside the Navigate method and navigated according to the different Navigator implementation.

public void navigate(@IdRes int resId, @Nullable Bundle args, @Nullable NavOptions navOptions,
            @Nullable Navigator.Extras navigatorExtras) {
        NavDestination currentNode = mBackStack.isEmpty()
                ? mGraph
                : mBackStack.getLast().getDestination();
        if (currentNode == null) {
            throw new IllegalStateException("no current navigation node");
        }
        @IdRes int destId = resId;
        //2. Obtain the corresponding NavAction based on the ID
        final NavAction navAction = currentNode.getAction(resId);
        Bundle combinedArgs = null;
        if(navAction ! =null) {
            if (navOptions == null) {
                navOptions = navAction.getNavOptions();
            }
            //3. Use NavAction to obtain the destination ID
            destId = navAction.getDestinationId();
            Bundle navActionArgs = navAction.getDefaultArguments();
            if(navActionArgs ! =null) {
                combinedArgs = newBundle(); combinedArgs.putAll(navActionArgs); }}if(args ! =null) {
            if (combinedArgs == null) {
                combinedArgs = new Bundle();
            }
            combinedArgs.putAll(args);
        }

        if (destId == 0&& navOptions ! =null&& navOptions.getPopUpTo() ! = -1) {
            popBackStack(navOptions.getPopUpTo(), navOptions.isPopUpToInclusive());
            return;
        }

        if (destId == 0) {
            throw new IllegalArgumentException("Destination id == 0 can only be used"
                    + " in conjunction with a valid navOptions.popUpTo");
        }
        //4. Use the destination ID attribute to find the destination to navigate to using the findDestination method
        NavDestination node = findDestination(destId);
        if (node == null) {
            final String dest = NavDestination.getDisplayName(mContext, destId);
            if(navAction ! =null) {
                throw new IllegalArgumentException("Navigation destination " + dest
                        + " referenced from action "
                        + NavDestination.getDisplayName(mContext, resId)
                        + " cannot be found from the current destination " + currentNode);
            } else {
                throw new IllegalArgumentException("Navigation action/destination " + dest
                        + " cannot be found from the current destination "+ currentNode); }}//5. Start navigation
        navigate(node, combinedArgs, navOptions, navigatorExtras);
    }


 private void navigate(@NonNull NavDestination node, @Nullable Bundle args,
            @Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) {
        boolean popped = false;
        boolean launchSingleTop = false;
        if(navOptions ! =null) {
            if(navOptions.getPopUpTo() ! = -1) { popped = popBackStackInternal(navOptions.getPopUpTo(), navOptions.isPopUpToInclusive()); } } Navigator<NavDestination> navigator = mNavigatorProvider.getNavigator( node.getNavigatorName()); Bundle finalArgs = node.addInDefaultArgs(args); NavDestination newDest = navigator.navigate(node, finalArgs, navOptions, navigatorExtras); . }Copy the code

findDestination

NavGraph is returned if the rollback stack is NULL, and the last item in the rollback stack is not returned if null.

  NavDestination findDestination(@IdRes int destinationId) {
        if (mGraph == null) {
            return null;
        }
        if (mGraph.getId() == destinationId) {
            return mGraph;
        }
        //1. If the rollback is null, return NavGraph. If the rollback is not null, return the last item in the rollback.
        NavDestination currentNode = mBackStack.isEmpty()
                ? mGraph
                : mBackStack.getLast().getDestination();
        NavGraph currentGraph = currentNode instanceof NavGraph
                ? (NavGraph) currentNode
                : currentNode.getParent();
        return currentGraph.findNode(destinationId);
    }
Copy the code

The realization of the FragmentNavigator

The above analysis brings us to the FragmentNavigator subclass. Take a look at FragmentNavigator. Navigate method. (1) call instantiateFragment to build Fragment instances via reflection mechanism (2) handle animation logic such as inbound and outbound (3) Finally call FragmentManager to handle navigation logic.

@Nullable
@Override
public NavDestination navigate(@NonNull Destination destination, @Nullable Bundle args,
        @Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) {
    if (mFragmentManager.isStateSaved()) {
        Log.i(TAG, "Ignoring navigate() call: FragmentManager has already"
                + " saved its state");
        return null;
    }
    String className = destination.getClassName();
    if (className.charAt(0) = ='. ') {
        className = mContext.getPackageName() + className;
    }
    // Build a Fragment instance using reflection
    final Fragment frag = instantiateFragment(mContext, mFragmentManager,
            className, args);
    frag.setArguments(args);
    final FragmentTransaction ft = mFragmentManager.beginTransaction();
    
    // Handle animation logic
    intenterAnim = navOptions ! =null ? navOptions.getEnterAnim() : -1;
    intexitAnim = navOptions ! =null ? navOptions.getExitAnim() : -1;
    intpopEnterAnim = navOptions ! =null ? navOptions.getPopEnterAnim() : -1;
    intpopExitAnim = navOptions ! =null ? navOptions.getPopExitAnim() : -1;
    if(enterAnim ! = -1|| exitAnim ! = -1|| popEnterAnim ! = -1|| popExitAnim ! = -1) { enterAnim = enterAnim ! = -1 ? enterAnim : 0; exitAnim = exitAnim ! = -1 ? exitAnim : 0; popEnterAnim = popEnterAnim ! = -1 ? popEnterAnim : 0; popExitAnim = popExitAnim ! = -1 ? popExitAnim : 0;
        ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim);
    }
    
    //FragmentManager to handle navigation logic
    ft.replace(mContainerId, frag);
    ft.setPrimaryNavigationFragment(frag);

    final @IdRes int destId = destination.getId();
    final boolean initialNavigation = mBackStack.isEmpty();
    final booleanisSingleTopReplacement = navOptions ! =null && !initialNavigation
            && navOptions.shouldLaunchSingleTop()
            && mBackStack.peekLast() == destId;

    boolean isAdded;
    if (initialNavigation) {
        isAdded = true;
    } else if (isSingleTopReplacement) {
        if (mBackStack.size() > 1) {
            mFragmentManager.popBackStack(
                    generateBackStackName(mBackStack.size(), mBackStack.peekLast()),
                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
            ft.addToBackStack(generateBackStackName(mBackStack.size(), destId));
        }
        isAdded = false;
    } else {
        ft.addToBackStack(generateBackStackName(mBackStack.size() + 1, destId));
        isAdded = true;
    }
    if (navigatorExtras instanceof Extras) {
        Extras extras = (Extras) navigatorExtras;
        for (Map.Entry<View, String> sharedElement : extras.getSharedElements().entrySet()) {
            ft.addSharedElement(sharedElement.getKey(), sharedElement.getValue());
        }
    }
    ft.setReorderingAllowed(true);
    ft.commit();
    if (isAdded) {
        mBackStack.add(destId);
        return destination;
    } else {
        return null; }}Copy the code

ActivityNavigator

ActivityNavigator eventually calls the startActivity method as well. Read the source code for yourself.

    @Nullable
    @Override
    public NavDestination navigate(@NonNull Destination destination, @Nullable Bundle args,
            @Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) {...if (navigatorExtras instanceof Extras) {
                Extras extras = (Extras) navigatorExtras;
                ActivityOptionsCompat activityOptions = extras.getActivityOptions();
                if(activityOptions ! =null) {
                    ActivityCompat.startActivity(mContext, intent, activityOptions.toBundle());
                } else{ mContext.startActivity(intent); }}else{ mContext.startActivity(intent); }... }Copy the code

3. Summary

  1. The NavHostFragment acts as a navigation carrier, is referenced in the Activity layout file (or dynamically in code), and holds a NavController reference to the navigation control class.
  2. The NavController delegates navigation to the Navigator class, which has two important subclasses FragmentNavigator and ActivityNavigator. The NavController class holds NavInflater class references.
  3. The NavInflater parses the Navnavigation file and builds the NavGraph.
  4. NavDestination holds Destination information, and there is a Destination class inside FragmentNavigator and ActivityNavigator that inherits NavDestination.
  5. During page navigation, FragmentManager handles fragment operations and startActivity handles activity.