【问题标题】:Shared viewModel with assisted injection and hilt具有辅助注入和刀柄的共享视图模型
【发布时间】:2022-01-16 04:29:33
【问题描述】:

我有一个活动。此活动正在接收一些参数。 目前,我可以使用这些参数通过辅助注入创建一个viewModel

//activity code
private val viewModel: ViewModel by viewModels {   
    val keyName = intent.extras?.getString(KEY_NAME).orEmpty()
    ViewModel.provideFactory(keyName)
}

现在,我有一个navHostFragment,导航图中的所有片段都将使用我之前在活动中创建的视图模型。 但我找不到分享该视图模型的方法

我已经知道我们可以使用activityViewModels 与活动共享视图模型

//fragment code
private val sharedViewModel: ViewModel by activityViewModels()

但是我的sharedViewModel 没有没有辅助参数的构造函数(并且在运行时失败)。

目前,我有两个解决方案

第一个选项:在每个片段中“创建”一个新的 viewModel,并使用 activityViewModels 从 Activity(或 navArgs)接收参数以共享同一个实例(我不喜欢这种方法,但是作品)

private val viewModel: ViewModel by activityViewModels {   
    val keyName = navArgs.keyName
    ViewModel.provideFactory(keyName)
}

第二个选项:从构造函数中移除辅助参数,并在viewModel中创建一个方法来设置我需要的信息:

@HiltViewModel
class ViewModel @Inject constructor(
    private val repository,
    .....
) : ViewModel() {

   fun setKeyName(keyName: String)....

所以,我的问题是......有没有办法在活动中创建一个带有辅助参数的 viewModel,并与片段共享该 viewModel?

【问题讨论】:

  • 所以你有一个负责从 Intent Extras 创建 ViewModel 的活动,并且你想让你的 Fragment 访问相同的 ViewModel(仍然使用 Intent Extras 作为键名)?或者您是否尝试将活动范围与仅发送到单个片段的参数混合在一起?
  • @ianhanniballake 我想与 navGraph 中的所有片段共享相同的视图模型。我的 viewModel 就像……一个 DetailsViewModel。因此,来自 viewModel 的一些基本信息将在所有片段中显示给用户(使用数据绑定),我正在 viewModel init 部分中检索信息
  • 我认为您没有回答我的问题。论据从何而来?它们是否纯粹来自活动意图附加内容?
  • @ianhanniballake,是的,目前我的论点来自额外的意图
  • 然后by activityViewModels()(使用@HiltViewModel,没有自定义工厂)和SavedStateHandle,正如Amjad在他的回答中提到的那样,自动辅助注入参数。

标签: android viewmodel dagger-hilt assisted-inject


【解决方案1】:

有了 hilt 库现在支持以 SavedStateHandle 作为参数的视图模型,并且值自动通过 SavedStateHandle 传递。您所要做的就是通过以下方式接收价值

@HiltViewModel
class ViewModel @Inject constructor(
    private val repository, savedStateHandle: SavedStateHandle
) : ViewModel() {

init {

        // Use the same argName as in your navigation graph
        val name : String = savedStateHandle["keyName"]
        
    }

【讨论】:

  • 该功能当然不需要 Safe Args;无论您是否使用 Safe Args,它都会自动适用于任何 Activity、Fragment 或 Navigation 目的地的参数。如果您不想记住您的 "keyName" 是什么,Navigation 2.4 确实提供了一种方便的方法 YourArgs.fromSavedStateHandle(),但即使这样也不是必需的,只是方便 :)
  • @ianhanniballake 这很好。答案已更新:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-10
相关资源
最近更新 更多