Android导航控制器组件的使用笔记

46 阅读3分钟

主要功能

在Android中,导航控制器(Navigation Controller)是用于管理应用程序中的导航操作的组件。它通常与Android Jetpack的导航组件一起使用,提供了一种简化的方式来处理应用程序的导航。

  1. 导航图:使用XML文件定义应用程序的导航结构,包括不同的目的地(Fragment、Activity等)和它们之间的关系。
  2. 导航操作:通过导航控制器执行导航操作,如跳转到另一个Fragment或返回上一个Fragment。
  3. 参数传递:支持在不同目的地之间传递参数。
  4. 深度链接:允许用户通过特定的URL直接导航到应用程序中的特定位置

Fragment的创建过程:

  1. 懒加载:导航组件采用懒加载的方式,只有在需要显示某个Fragment时,导航控制器才会创建该Fragment。这意味着在导航图中定义的Fragment不会在应用启动时全部创建,而是根据用户的导航操作动态创建。
  2. Fragment的生命周期:每个Fragment的生命周期遵循标准的Android Fragment生命周期。当Fragment被导航到时,它会调用onCreateView()等生命周期方法进行初始化。当用户返回到上一个Fragment时,当前Fragment会被销毁或暂停。
  3. Fragment的重用:如果用户在导航过程中多次访问同一个Fragment,导航控制器会重用已经创建的Fragment实例,而不是每次都创建新的实例。这有助于提高性能和减少内存使用。

使用步骤:

  1. 添加依赖:在build.gradle文件中添加导航组件的依赖。
implementation "androidx.navigation:navigation-fragment-ktx:2.5.3"  
implementation "androidx.navigation:navigation-ui-ktx:2.5.3"
  1. 创建导航图:在res/navigation目录下创建一个XML文件,定义导航图。
  2. 设置导航控制器:在Activity或Fragment中获取导航控制器并设置导航图。
val navController = findNavController(R.id.nav_host_fragment)

4.执行导航:使用导航控制器执行导航操作。

navController.navigate(R.id.action_currentFragment_to_targetFragment)

5.处理返回:可以通过navController.popBackStack()来处理返回操作。

下面是一个简单的Android应用程序示例,演示如何使用导航组件在多个Fragment之间进行导航。这个示例包含三个Fragment:FragmentAFragmentBFragmentC

1. 添加依赖

build.gradle文件中添加导航组件的依赖:

dependencies {  
    implementation "androidx.navigation:navigation-fragment-ktx:2.5.3"  
    implementation "androidx.navigation:navigation-ui-ktx:2.5.3"  
}  

2. 创建导航图

res/navigation目录下创建一个名为nav_graph.xml的文件,定义导航图:

<?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"  
    app:startDestination="@id/fragmentA">  

    <fragment  
        android:id="@+id/fragmentA"  
        android:name="com.example.app.FragmentA"  
        android:label="Fragment A" />  
    
    <fragment  
        android:id="@+id/fragmentB"  
        android:name="com.example.app.FragmentB"  
        android:label="Fragment B" />  
    
    <fragment  
        android:id="@+id/fragmentC"  
        android:name="com.example.app.FragmentC"  
        android:label="Fragment C" />  
</navigation>  

3. 创建Fragment

创建三个Fragment类:FragmentAFragmentBFragmentC

FragmentA.kt

class FragmentA : Fragment(R.layout.fragment_a) {  
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {  
        super.onViewCreated(view, savedInstanceState)  

        view.findViewById<Button>(R.id.buttonToB).setOnClickListener {  
            findNavController().navigate(R.id.action_fragmentA_to_fragmentB)  
        }  
    }  
}  

FragmentB.kt

class FragmentB : Fragment(R.layout.fragment_b) {  
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {  
        super.onViewCreated(view, savedInstanceState)  

        view.findViewById<Button>(R.id.buttonToC).setOnClickListener {  
            findNavController().navigate(R.id.action_fragmentB_to_fragmentC)  
        }  

        view.findViewById<Button>(R.id.buttonBackToA).setOnClickListener {  
            findNavController().popBackStack()  
        }  
    }  
}  

FragmentC.kt

class FragmentC : Fragment(R.layout.fragment_c) {  
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {  
        super.onViewCreated(view, savedInstanceState)  

        view.findViewById<Button>(R.id.buttonBackToB).setOnClickListener {  
            findNavController().popBackStack()  
        }  
    }  
}  

4. 创建布局文件

为每个Fragment创建布局文件。

fragment_a.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:orientation="vertical"  
    android:gravity="center">  

    <Button  
        android:id="@+id/buttonToB"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="Go to Fragment B" />  
</LinearLayout>  

fragment_b.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:orientation="vertical"  
    android:gravity="center">  

    <Button  
        android:id="@+id/buttonToC"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="Go to Fragment C" />  

    <Button  
        android:id="@+id/buttonBackToA"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="Back to Fragment A" />  
</LinearLayout>  

fragment_c.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:orientation="vertical"  
    android:gravity="center">  

    <Button  
        android:id="@+id/buttonBackToB"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="Back to Fragment B" />  
</LinearLayout>  

5. 设置导航控制器

在主Activity中设置导航控制器:

class MainActivity : AppCompatActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContentView(R.layout.activity_main)  

        val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment  
        val navController = navHostFragment.navController  
        NavigationUI.setupActionBarWithNavController(this, navController)  
    }  

    override fun onSupportNavigateUp(): Boolean {  
        val navController = findNavController(R.id.nav_host_fragment)  
        return navController.navigateUp() || super.onSupportNavigateUp()  
    }  
}  

6. 主布局文件

activity_main.xml中添加NavHostFragment:

<androidx.fragment.app.FragmentContainerView  
    xmlns:android="http://schemas.android.com/apk/res/android"  
    android:id="@+id/nav_host_fragment"  
    android:name="androidx.navigation.fragment.NavHostFragment"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    app:navGraph="@navigation/nav_graph"  
    app:defaultNavHost="true" />