Jetpack Compose 状态提升、预览和 ViewModel 最佳实践

Mat*_*lis 13 android state kotlin android-jetpack-compose android-jetpack-compose-preview

因此,Jetpack Compose 中的建议似乎是从可组合项中提升状态,使它们成为无状态、可重用和可测试,并允许在预览中轻松使用它们。\n因此,不要使用类似的东西

\n
@Composable\nfun MyInputField() {\n    var text by remember { mutableStateOf("") }\n    TextField(value = text, onValueChange = { text = it })\n}\n
Run Code Online (Sandbox Code Playgroud)\n

你会像这样提升状态

\n
@Composable\nfun MyInputField(text: String, onTextChange: (String) -> Unit) {\n    TextField(value = text, onValueChange = onTextChange)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这很好,但是一些更复杂的用途呢?\n让我们假设我有一个由可组合项表示的屏幕,在 View 和 ViewModel 之间具有多种交互。该屏幕分为多个内部可组合项(例如,一个用于标题,一个用于正文,而正文又分为几个较小的可组合项)

\n
    \n
  • 您无法在可组合项中创建 ViewModel(viewModel()至少可以手动实例化一个)并在Preview(预览版不支持像这样创建视图模型)中使用此可组合项
  • \n
  • 在内部可组合项中使用 ViewModel 将使它们成为有状态的,不是吗?
  • \n
\n

因此,我看到的“最干净”的解决方案是仅在最高可组合级别实例化我的视图模型,然后仅将val表示状态的 s 传递给子可组合项,并回调 ViewModel 函数。

\n

但这很疯狂,我不会通过单独的参数将所有 ViewModel 状态和函数传递给所有需要它们的可组合项。\n将它们分组到一个data class示例中可能是一个解决方案

\n
data class UiState(\n  val textInput: String,\n  val numberPicked: Int,\n  \xe2\x80\xa6\xe2\x80\xa6\n
Run Code Online (Sandbox Code Playgroud)\n

也许还可以创建另一个用于回调?\n但这仍然是创建一个全新的类,只是为了模仿视图模型已有的内容。

\n

我实际上不知道最好的方法是什么,而且我在任何地方都找不到任何相关信息

\n

And*_*Dev 0

Jetmagic 是一个开源框架,它恰好解决了这个问题,同时也解决了 Google 在开发 Compose 时忽略的其他主要问题。关于您的请求,您根本不传入视图模型作为参数。Jetmagic 遵循“提升状态”模式,但它为您管理视图模型并使它们与您的可组合项保持关联。它将可组合项视为资源,其方式类似于旧视图系统处理 xml 布局的方式。您不需要直接调用可组合函数,而是要求 Jetmagic 的框架为您提供最适合设备配置的可组合“实例”。请记住,在旧的基于 xml 的系统下,您可以有效地为同一屏幕拥有多种布局(例如一个用于纵向模式,另一个用于横向模式)。Jetmagic 会为您选择正确的一款。当它执行此操作时,它会为您提供一个对象,用于管理可组合项及其相关视图模型的状态。

您可以轻松地在屏幕层次结构中的任何位置访问视图模型,而无需将视图模型作为参数沿层次结构传递。这部分是使用 CompositionLocalProvider 完成的。

Jetmagic 旨在处理构成屏幕的顶级可组合项。在可组合层次结构中,您仍然像平常一样调用可组合项,但在有意义的地方使用状态提升。

最好的办法是下载 Jetmagic 并尝试一下。它有一个很棒的演示,说明了您正在寻找的解决方案:

https://github.com/JohannBlake/Jetmagic