ViewModelProviders在我的片段内部不起作用

时间:2019-06-28 17:24:49

标签: android kotlin mvvm fragment android-viewmodel

这就是我想要做的。

  • 在片段内设置ArrayList的对象
  • FragmentActivity中的观察者那里获取该数组 容器(托管所有片段的活动)

所以,我要做的是以下事情。

首先,我在其中设置SharedViewModel并从中获取数据:

SharedViewModel.kt

class SharedViewModel: ViewModel() {

    var personArrayObj:MutableLiveData<ArrayList<Person>> = MutableLiveData()

    fun setPersonArray(personArray:ArrayList<Person>){
        personArrayObj.value = personArray
    }

    val getPersonArray:LiveData<ArrayList<Person>>
    get() = personArrayObj

}

现在,我在托管所有片段创建的ViewModel中实例化此MainActivity,因此,无论片段集位于何处,我都可以从ArrayData中获取它:

MainActivity.kt

class MainActivity: FragmentActivity(){

private lateinit var viewModel:SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewModel = ViewModelProviders.of(this).get(SharedViewModel::class.java)
        viewModel.getPersonArray.observe(this, Observer { it:ArrayList<Person>
            Log.d("Array:",""+it)
        })
    }

}

然后,我要做的最后一件事是从我想要的任何片段中设置该Array的值,然后,如果该值已更改,则将触发主机Activity,因此,要做到这一点,我简单地做一个{ {1}}在我想要的片段上。

问题

当我尝试实例化任何片段中的viewModel.setValue(personArray)时,我会遇到此问题:

enter image description here

我试图断言!对于null,也可以使用let,但不能使用,我想知道SharedViewModel的来源是什么

如果我使用FragmentActivity而不是viewLifecycleOwner,它对我说,不能使用 Fragment FragmentActivity 来调用它?

有任何线索吗?

谢谢。

5 个答案:

答案 0 :(得分:2)

片段提供了一种辅助方法来检索非null活动-requireActivity()。使用它代替activity

viewModel = ViewModelProviders.of(requireActivity()).get(SharedViewModel::class.java)

作为替代方案,您可以在应用程序中包含fragment-ktx依赖项,并使用by activityViewModels() Kotlin属性扩展而不是完全使用ViewModelProviders.of()

val viewModel: SharedViewModel by activityViewModels()

答案 1 :(得分:1)

ViewModelProviders.of() 已弃用。因此,我们可以像下面那样初始化视图模型。

 viewModel = ViewModelProvider(requireActivity()).get(SampleViewModel::class.java)

答案 2 :(得分:0)

基本上,问题在于片段类内部的活动上下文为空,并且ViewModelPorviders需要非空上下文与之合作。

一种解决方案是使您的ViewModel对象可空 (因为您的活动可为空)在片段内,如下所示:

var viewModel: SharedViewModel? = null

然后在初始化期间

viewModel = activity?.let { ViewModelProviders.of(it).get(SharedViewModel::class.java) }

答案 3 :(得分:0)

好吧,我没看到

我在我的 Fragment 中创建了viewModel的一个实例,而在我的 MainActivity 中创建了一个实例,因此,这样做可以防止观察者工作。

为解决这个问题,我只做了一个简单的方法即可返回我在MainActivity内创建的实例

 fun getViewModelInstance():SharedViewModel = viewModel

然后我只需从任何Fragment调用该实例即可使用它

(activity as MainActivity).getViewModelInstance().setPersonArray(personArray)

答案 4 :(得分:0)

将东西放在onActivityCreated()中,而不是onCreateView()中。 这将解决getActivity()可为空的问题... 因为根据片段的生命周期,onActivityCreated()在onCreareView()之后。 活动是在onActivityCreated()的调用上创建的... 因此,getActivity()将返回刚刚创建的活动