首页 > 解决方案 > 片段如何通过 ViewModelInject 将 bundle 传递给 viewModel

问题描述

我使用 hilt 在 vi​​ewModel 中注入我想要的所有内容,我发现 hilt 通过 @ViewModelInject 支持 SavedStateHandle,因此如果我愿意,任何传递给它的捆绑数据都可以取回。

class TestViewModel @ViewModelInject constructor(
    private val testRepository: TestRepository,
    @Assisted private val state: SavedStateHandle
) : ViewModel() {
    val testItem = state["test"] ?: "defaultValue"
}

@AndroidEntryPoint
class TestFragment : Fragment() {

    private val viewModel: TestViewModel by viewModels() // How to pass bundle to the init viewModel?

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding = FragmentTestBinding.inflate(inflater)
        binding.lifecycleOwner = this
        binding.viewModel = viewModel
        ...
    }
}

这似乎是使用 ViewModelFactory 用 bundle 初始化 viewModel 的方式。

interface ViewModelAssistedFactory<T : ViewModel> {
    fun create(state: SavedStateHandle): T
}

class TestViewModelFactory @Inject constructor(
    private val testRepository: TestRepository
) : ViewModelAssistedFactory<TestViewModel> {
    fun create(handle: SavedStateHandle) {
      return TestViewModel(handle, testRepository)
    }
}

class TestViewModel(
    private val state: SavedStateHandle
    private val testRepository: TestRepository,
) : ViewModel() {
    val id = state["test"] ?: "defaultValue"
}

标签: android

解决方案


如果我正确理解您的问题,您希望实例化 ViewModel 并传入捆绑包,我怀疑Injecting ViewModel with Dagger Hilt文章可能会有所帮助。

向下滚动,有 2 个示例使用不同的方法来实例化 ViewModel,其中一个特别是传递 Bundle。

这是另一个很好的资源:没有更多工厂需要 ViewModel with Dependencies

这就是我所做的,可能并不优雅,但效果很好:

class dataViewModel @ViewModelInject constructor(
    val stateData: StateData,
    @Assisted private val savedStateHandle: SavedStateHandle
): ViewModel() {

然后,要实例化 viewModel,您需要一个模块定义:

@Module
@InstallIn(ApplicationComponent::class)
class StateDataModule {

    @Singleton
    @Provides
    fun provideStateData(): StateData {
        return StateData(null, null)
    }
}

然后,在使用它的类中,我设置值,ViewModel 保留所有实例和跨活动的值(这是我这样做的主要原因)。

dataViewModel.stateData.[property] = blah

推荐阅读