【问题标题】:Hilt-Dagger ViewModel calling from Fragment从 Fragment 调用 Hilt-Dagger ViewModel
【发布时间】:2020-08-04 09:35:15
【问题描述】:

我正在使用ViewModel 来更新操作栏中的标题

共享视图模型

class SharedViewModel @ViewModelInject constructor(
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    val title: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }

    val backButton: MutableLiveData<Boolean> by lazy {
        MutableLiveData<Boolean>()
    }
}

MainActivity 观察者

@AndroidEntryPoint
...
sharedViewModel.title.observe(this, Observer {
    supportActionBar?.title = it
})

使用下面的代码似乎在Fragment 中创建了一个新实例(在调试器中检查):

@AndroidEntryPoint
...
private val viewModel: SharedViewModel by viewModels()

但似乎是这样工作的

val viewModel = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)

Article reference

这是应该这样做还是我做错了什么?

谢谢!

【问题讨论】:

    标签: android kotlin viewmodel dagger dagger-hilt


    【解决方案1】:

    如果您想在片段中使用共享视图模型,您必须使用 by activityViewModels() 而不是 by viewModels()

    为什么下一行可以工作,而 by viewModels() 却不行?

    ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)
    

    因为默认情况下viewModels()ownerProducer 参数值为{ this }。为了更好地理解它,这里是源代码:

    @MainThread
    inline fun <reified VM : ViewModel> Fragment.viewModels(
        noinline ownerProducer: () -> ViewModelStoreOwner = { this },
        noinline factoryProducer: (() -> Factory)? = null
    ) = createViewModelLazy(VM::class, { ownerProducer().viewModelStore }, factoryProducer)
    

    如您所见,它是Fragment 类的扩展函数。这意味着ViewModelStoreOwner片段。片段从堆栈中删除后,它存储在视图模型存储中的所有视图模型都消失了。

    但如果您使用by activityViewModels(),则您使用Activity 作为视图模型商店所有者。注意使用requireActivity().viewModelStore 而不是ownerProducer().viewModelStore,默认情况下是Fragment

    @MainThread
    inline fun <reified VM : ViewModel> Fragment.activityViewModels(
        noinline factoryProducer: (() -> Factory)? = null
    ) = createViewModelLazy(VM::class, { requireActivity().viewModelStore },
        factoryProducer ?: { requireActivity().defaultViewModelProviderFactory })
    

    最终,createViewModelLazy 打来电话

    ViewModelProvider(store, factory).get(viewModelClass.java)
    

    这相当于您使用手动创建视图模型

    ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)
    

    如何解决这个问题?

    使用by activityViewModels()

    @AndroidEntryPoint
    ...
    private val viewModel: SharedViewModel by activityViewModels()
    

    注意:by activityViewModels()by viewModels() 只是 ViewModelProvider(...).get(...) 的延迟加载实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-14
      • 1970-01-01
      • 1970-01-01
      • 2021-02-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多