首页 > 解决方案 > 如何检查给定 ViewModelProvider 的 ViewModel 是否已存在

问题描述

该视频(MVVM 和嵌套片段/视图:ViewModel 合同 - Marcos Paulo Damesceno,Bret Erickson droidcon 旧金山 2019 年)展示了一种使用ViewModel.

我出于学习目的而实施它,但我被卡住了。

// 18:35 of the video

private const val VM_KEY = "view_model_contract_key"

fun <T> Fragment.viewModelContracts() = lazy {
    val clazz: Class<ViewModel> = arguments?.getSerializable(VM_KEY) as Class<ViewModel>
    val viewModelProvider = ViewModelProvider(requireActivity())

    return@lazy viewModelProvider.get(clazz) as T
}

传递的ViewModelStoreOwneras 参数是一个Activity,但如果我Fragment在另一个内部有一个Fragment它们都共享相同ViewModel的,则ViewModel返回的viewModelContracts()对象将是与 Parent 创建的对象不同的对象Fragment

interface ChildViewModelContract {
    // ...
}

class SomeViewModel : ViewModel(), ChildViewModelContract {
    // ...
}

class ParentFragment: Fragment {
    private val viewModel: SomeViewModel by viewModels()

    // ...
}

class ChildFragment: Fragment {
    private val viewModelContract: ChildViewModelContract by viewModelContracts()

    // ...
}

理想的解决方案是检查父片段的 是否fun <T> Fragment.viewModelContracts()存储在其中,如果没有,则使用Activity 的。但我不知道该怎么做。ViewModelProviderViewModelViewModelProvider

fun <T> Fragment.viewModelContracts() = lazy {
    val clazz: Class<ViewModel> = arguments?.getSerializable(VM_KEY) as Class<ViewModel>
    
    val parentFragment = parentFragment
    if (parentFragment != null) {
        val viewModelProvider = ViewModelProvider(parentFragment)
        // is there any way to do something like this?
        if (viewModelProvider.isViewModelStored(clazz)) {
            return@lazy viewModelProvider.get(clazz) as T 
        }
    }
    
    val viewModelProvider = ViewModelProvider(requireActivity())
    
    return@lazy viewModelProvider.get(clazz) as T
}

标签: androidandroid-fragmentsandroid-viewmodel

解决方案


推荐阅读