借助 Navigation Compose API,您可以在 Compose 应用中的可组合项之间导航,同时利用 Jetpack Navigation 组件、基础架构和功能。
本页介绍了如何从基于 fragment 的 Jetpack Navigation 迁移到 Navigation Compose,这是向 Jetpack Compose 进行基于 View 的界面更大规模迁移的一部分。
迁移先决条件
当您能够将所有 fragment 替换为相应的屏幕可组合项后,就可以迁移到 Navigation Compose。Screen 可组合项可以包含 Compose 和 View 内容的混合,但所有导航目的地都必须是可组合项才能启用 Navigation Compose 迁移。在此之前,您应该继续在互操作视图和 Compose 代码库中使用基于 fragment 的 Navigation 组件。如需了解详情,请参阅导航互操作性文档。
在仅限 Compose 的应用中使用 Navigation Compose 不是前提条件。您可以继续使用 基于 fragment 的 Navigation 组件,前提是您保留 fragment 来托管可组合内容。
迁移步骤
无论您是遵循我们推荐的迁移策略,还是采取其他方法,您都需要实现所有导航目的地都是屏幕可组合项,而 fragment 仅充当可组合容器。在此阶段,您可以迁移到 Navigation Compose。
如果您的应用已在遵循 UDF 设计模式和我们的架构指南,迁移到 Jetpack Compose 和 Navigation Compose 应该无需对应用的其他层(界面层除外)进行重大重构。
如需迁移到 Navigation Compose,请按以下步骤操作:
- 将 Navigation Compose 依赖项添加到您的应用。
创建一个
App-level
可组合项,并将其添加到Activity
作为 Compose 入口点,从而替换 View 布局的设置:class SampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // setContentView<ActivitySampleBinding>(this, R.layout.activity_sample) setContent { SampleApp(/* ... */) } } }
设置
NavController
时,所有需要引用它的可组合项都可以访问它(这通常位于App
可组合项内)。此方法遵循状态提升原则,并允许您将NavController
用作在可组合屏幕之间导航和维护返回堆栈的可信来源:@Composable fun SampleApp() { val navController = rememberNavController() // ... }
在 App 可组合项内创建应用的
NavHost
,并传递navController
:@Composable fun SampleApp() { val navController = rememberNavController() SampleNavHost(navController = navController) } @Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = "first") { // ... } }
添加
composable
目的地以构建导航图。如果每个屏幕之前都已迁移到 Compose,此步骤仅包括从 fragment 将这些屏幕可组合项提取到composable
目的地:class FirstFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { setContent { // FirstScreen(...) EXTRACT FROM HERE } } } } @Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = "first") { composable("first") { FirstScreen(/* ... */) // EXTRACT TO HERE } composable("second") { SecondScreen(/* ... */) } // ... } }
如果您遵循有关设计 Compose 界面架构的指南,特别是如何将
ViewModel
和导航事件传递给可组合项,则下一步就是更改为每个屏幕可组合项提供ViewModel
的方式。您通常可以通过hiltViewModel
将 Hilt 注入及其集成点与 Compose 和 Navigation 集成:@Composable fun FirstScreen( // viewModel: FirstViewModel = viewModel(), viewModel: FirstViewModel = hiltViewModel(), onButtonClick: () -> Unit = {}, ) { // ... }
将所有
findNavController()
导航调用替换为navController
调用,并将这些调用作为导航事件传递给每个可组合屏幕,而不是传递整个navController
。此方法遵循将可组合函数中的事件公开给调用方的最佳实践,并将navController
保留为单一可信来源。- 如果您之前使用过 Safe Args 插件生成导航路线和操作,请将其替换为 route(一个指向您的可组合项的字符串路径,对于每个目的地而言都是唯一的)。
- 如需在传递数据时替换 Safe Args,请参阅使用实参进行导航。
关于 Navigation Compose 中的类型安全,请参阅下文中的 Safe Args 部分。
@Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = "first") { composable("first") { FirstScreen( onButtonClick = { // findNavController().navigate(firstScreenToSecondScreenAction) navController.navigate("second_screen_route") } ) } composable("second") { SecondScreen( onIconClick = { // findNavController().navigate(secondScreenToThirdScreenAction) navController.navigate("third_screen_route") } ) } // ... } }
移除所有 fragment、相关的 XML 布局、不必要的导航和其他资源,以及过时的 fragment 和 Jetpack Navigation 依赖项。
您可以在设置文档中找到相同的步骤,以及更多与 Navigation Compose 相关的详细信息。
常见用例
无论您使用哪种 Navigation 组件,导航的原则都适用。
迁移时的常见用例包括:
如需详细了解这些用例,请参阅使用 Compose 进行导航。
Safe Args
与 Jetpack Navigation 不同,Navigation Compose 不支持使用 Safe Args 插件生成代码。您可以改为使用 Navigation Compose 实现类型安全,方法是构建代码,使其在运行时具有类型安全性。
在导航时检索复杂数据
Navigation Compose 基于字符串路线,与 Jetpack Navigation 不同,不支持将自定义 Parcelable 和可序列化资源作为参数传递。
我们强烈建议您在导航时不要传递复杂的数据对象。请在执行导航操作时将唯一标识符或其他形式的 ID 等最少的必要信息作为参数传递。您应将复杂对象以数据存储在单一可信来源(例如数据层)中。如需了解详情,请参阅在导航时检索复杂数据。
如果您的 Fragment 将复杂对象作为参数传递,不妨考虑先重构您的代码,使其允许从数据层存储和提取这些对象。如需查看相关示例,请参阅 Now in Android 代码库。
限制
本部分介绍了 Navigation Compose 的当前限制。
逐步迁移到 Navigation Compose
目前,如果仍在代码中将 fragment 用作目的地,则无法使用 Navigation Compose。如需开始使用 Navigation Compose,所有目的地都需要是可组合项。您可以在问题跟踪器上跟踪此功能请求。
过渡动画
从 Navigation 2.7.0-alpha01 开始,NavHost
现在支持设置自定义转场效果(以前为 AnimatedNavHost
)。如需了解详情,请仔细阅读版本说明。
了解详情
如需详细了解如何迁移到 Navigation Compose,请参阅以下资源:
- Navigation Compose Codelab:通过实操 Codelab 了解 Navigation Compose 的基础知识。
- Now in Android 代码库:完全使用 Kotlin 和 Jetpack Compose 构建的功能齐全的 Android 应用,遵循 Android 设计和开发最佳实践,并包含 Navigation Compose。
- 将 Sunflower 迁移到 Jetpack Compose:一篇博文,介绍了 Sunflower 示例应用从 View 到 Compose 的迁移历程,其中还包括迁移到 Navigation Compose。
- 适用于各种屏幕的 Jetnews:一篇博客文章,介绍了 Jetnews 示例的重构和迁移,以支持使用 Jetpack Compose 和 Navigation Compose 的所有屏幕。
为您推荐
- 注意:当 JavaScript 处于关闭状态时,系统会显示链接文字
- 使用 Compose 进行导航
- Compose 和其他库
- 其他注意事项