如何使用 Jetpack Compose 和 Compose Navigation 处理 Android 活动?

MrM*_*imn 28 android kotlin android-jetpack-compose

我目前正在研究 Jetpack Compose,试图使用现代 Android 架构组件构建功能丰富的应用程序。传统上,我的应用程序中的每个屏幕(或导航单元)都是一个 Activity 或一个 Fragment,每个屏幕都有自己的生命周期绑定,但使用 Jetpack Compose 和 Compose Navigation 库,我会执行以下操作:

MainActivity.kt

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val navController = rememberNavController()

            NavHost(navController = navController, startDestination = "main") {
                composable("main") { MainScreen(navController) }
                // More composable calls
            }
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

哪里MainScreen只是一个可组合项。我的问题是:

  • 此可组合项的“生命周期”相当于什么?假设我想在屏幕加载、销毁等时执行某些操作。这可能与我有更多屏幕和它们之间的导航的情况更相关
  • 是否有某种方法可以在 Compose 和标准活动之间进行集成?也就是说,像您一样为屏幕定义活动,每个活动都是一个ComponentActivity并定义自己的可组合布局?是否因某种原因而灰心丧气?

Phi*_*hov 53

Compose 应用程序设计用于没有片段的单活动架构。

您仍然可以拥有多个活动或片段并setContent在每个活动或片段中使用,但在这种情况下,活动之间的数据传输就落在您的肩上。如果您要将新的 Compose 屏幕添加到以旧方式构建的现有应用程序中,请使用此方法。

但借助 Compose,可以更轻松地使用 Compose Navigation 在单个 Activity 中完成所有导航。代码少得多,由于没有不必要的代码层而具有更好的性能,易于传输数据等。

要使用视图生命周期,请查看compose side-effects

  1. LaunchedEffect可用于在视图出现时执行操作。它还在绑定到当前可组合项的协程上下文上运行:您可以轻松运行挂起函数,并且当视图从视图层次结构中消失时 - 协程将被取消。
  2. DisposableEffect可用于订阅/取消订阅回调。

当您旋转屏幕时,无论您按下哪个键,所有效果都会重新启动。

@Composable
fun MainScreen(navController: NavController) {
    LaunchedEffect(Unit) {
        println("LaunchedEffect: entered main")
        var i = 0
        // Just an example of coroutines usage
        // don't use this way to track screen disappearance
        // DisposableEffect is better for this
        try {
            while (true) {
                delay(1000)
                println("LaunchedEffect: ${i++} sec passed")
            }
        } catch (cancel: CancellationException) {
            println("LaunchedEffect: job cancelled")
        }
    }
    DisposableEffect(Unit) {
        println("DisposableEffect: entered main")
        onDispose {
            println("DisposableEffect: exited main")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

另请注意,在这两种情况下,以及在 compose 中的许多其他情况下,您都会传递key给这些函数。这有助于 compose 了解何时应重新计算值。在我的示例中,它是Unit,这意味着在视图消失之前它不会改变。但是,如果您创建一个remember值,使用视图模型中的另一个动态值,或者将另一个参数传递给可组合项,您可以将其作为 a 传递key,这将取消当前LaunchedEffect作业并调用onDisposefor DisposableEffect,并且您的作业将使用更新后的内容重新启动key值重新启动。您可以传递任意数量的密钥。

在文档中阅读有关 Compose 中状态的更多信息。

  • “Compose 应用程序被设计为在没有片段的单活动架构中使用。”是一个非常有用的说法。只是好奇,您在文档中的哪里看到了这一点?我想看看我怎么会错过这么重要的声明。 (20认同)
  • @KevinLe-Khnle 我不知道我在哪里读到这篇文章,但对我来说这似乎非常合乎逻辑。您可以进行 Compose 导航,并且使用片段或多个活动比使用纯 Compose 实现相同的功能要复杂得多。 (6认同)