使用Factory创建共享ViewModel

问题描述 投票:0回答:2

我有一个带有 3 个选项卡的 TabLayout 的 DocumentsFragment:

TabRulesFragment, TabProceduresFragment, TabGuidanceFragment

在 DocumentsFragment 中,我使用工厂初始化共享 viewModel、DocumentsSharedViewModel:

class DocumentsFragment : Fragment() {

    private lateinit var sharedViewModel: DocumentsSharedViewModel
    private lateinit var viewPager2: ViewPager2
    private lateinit var documentsCollectionAdapter: DocumentsCollectionAdapter

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        val program = DocumentsFragmentArgs.fromBundle(requireArguments()).program
        val name = DocumentsFragmentArgs.fromBundle(requireArguments()).name

        val viewModelFactory = DocumentsSharedViewModelFactory(program, name)
        sharedViewModel = ViewModelProvider(this, viewModelFactory)[DocumentsSharedViewModel::class.java]

在文档片段和 3 个选项卡片段之间共享数据。当我尝试连接到选项卡片段之一(例如 TabRulesFragment)中的共享 viewModel 时:

class TabRulesFragment : Fragment() {

    private lateinit var tabRulesRecyclerView: RecyclerView

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {

        val sharedViewModel : DocumentsSharedViewModel by viewModels()
        val binding = TabRulesFragmentBinding.inflate(layoutInflater)
        binding.viewModel = sharedViewModel

我收到一个错误,无法创建 DocumentsSharedViewModel 的实例:

java.lang.RuntimeException: Cannot create an instance of class com.smellydogcoding.westvirginiaelectronicfieldguide.ui.documents.DocumentsSharedViewModel
        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:188)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:238)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:112)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:169)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:139)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:44)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:31)
        at com.smellydogcoding.westvirginiaelectronicfieldguide.ui.documents.rulesTab.TabRulesFragment.onCreateView$lambda-0(TabRulesFragment.kt:30)
        at com.smellydogcoding.westvirginiaelectronicfieldguide.ui.documents.rulesTab.TabRulesFragment.onCreateView(TabRulesFragment.kt:32)

我假设 viewModelProvider 正在寻找工厂(它在 TabRulesFragment 中不存在,因为它在 DocumentsFragment 中),并在找不到它时抛出错误。有没有办法使用共享数据模型中的数据而不创建它的另一个实例?

android android-viewmodel
2个回答
5
投票

如果您想将 ViewModel 范围限定为可以在片段之间共享的所属 Activity,则可以使用以下命令在两个片段中获取它。

val sharedModel: DocumentsSharedViewModel by activityViewModels()

根据 docs,其中有一个简单的示例,其中两个片段都可以访问相同的 ViewModel

class ListFragment : Fragment() {

    // Use the 'by activityViewModels()' Kotlin property delegate
    // from the fragment-ktx artifact
    private val model: SharedViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        //...
    }
}

class DetailFragment : Fragment() {

    // Use the 'by activityViewModels()' Kotlin property delegate
    // from the fragment-ktx artifact
    private val model: SharedViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        //...
    }
}

正如评论中所指出的,如果您希望 ViewModel 保持在父片段范围内,而不是使用活动范围,您可以使用它来在子片段中访问它

val sharedModel: DocumentsSharedViewModel by viewModels({ requireParentFragment() })

0
投票

如果您有 ViewModel Factory,则必须将此代码添加到两个片段中。

val共享模型:ActivityViewModels{DocumentsSharedViewModel.Factory}的DocumentsSharedViewModel

© www.soinside.com 2019 - 2024. All rights reserved.