如何将 id 和应用程序传递给 Jetpack Compose 中的 viewModel/viewModelFactory?

Oma*_*led 9 android kotlin android-jetpack-navigation android-jetpack-compose

我使用 Jetpack Compose 和导航撰写,我想将 id 传递给此viewmodel

class RecallViewModel(private val id:Long,application: Application):AndroidViewModel(application) {
  ............................
}

Run Code Online (Sandbox Code Playgroud)

可组合函数:

我不知道如何获得application可组合函数:

@Composable
fun RecallScreen(
    id:Long,
    onEnd:() -> Unit
){
       val recallViewModel = viewModel(factory = RecallViewModelFactory(
id = id,application = "i don't know how to get application"))

}

Run Code Online (Sandbox Code Playgroud)

和工厂

class RecallViewModelFactory(private val id:Long,val application: Application):ViewModelProvider.AndroidViewModelFactory(application) {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        return RecallViewModel(id,application) as T
    }
}
Run Code Online (Sandbox Code Playgroud)

        composable(
            "${Routes.recall}/{id}",
            arguments = listOf(navArgument("id") { type = NavType.LongType })
        ) {
            RecallScreen(
                id = it.arguments!!.getLong("id"),
                onEnd = {navController.navigateUp()}
            )
        }

Run Code Online (Sandbox Code Playgroud)

ian*_*ake 42

Application要回答您的问题:您从对象中检索LocalContext

val context = LocalContext.current
val application = context.applicationContext as Application
Run Code Online (Sandbox Code Playgroud)

但是,使用 Navigation Compose 时,您不需要手动将任何参数传递给 ViewModel。相反,您可以利用ViewModel 中对 SavedState 的内置支持,SavedStateHandle并向 ViewModel添加参数。这SavedStateHandle是一个键/值映射,会自动填充目标的参数。

这意味着您的 ViewModel 变为:

class RecallViewModel(
    application: Application,
    savedStateHandle: SavedStateHandle
):AndroidViewModel(application) {

  // Get your argument from the SavedStateHandle
  private val id: Long = savedStateHandle.get("id")

  ............................
}
Run Code Online (Sandbox Code Playgroud)

并且您不再需要从参数中手动解析 ID 或将其传递给 ViewModel:

composable(
    "${Routes.recall}/{id}",
    arguments = listOf(navArgument("id") { type = NavType.LongType })
) {
    RecallScreen(
        onEnd = {navController.navigateUp()}
    )
}
Run Code Online (Sandbox Code Playgroud)
@Composable
fun RecallScreen(
    onEnd:() -> Unit
) {
    val recallViewModel: RecallViewModel = viewModel()
}
Run Code Online (Sandbox Code Playgroud)