ViewModelProviders 在我的 Fragment 中不起作用

ViewModelProviders is not working inside my Fragment

这就是我想要做的。

所以,我所做的如下。

首先,我创建了 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

}

现在,我在承载所有片段创建的 MainActivity 中实例化此 ViewModel,因此,我可以从片段集的任何地方获取 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)
        })
    }

}

然后我需要做的最后一件事是从我想要的任何片段设置该数组的值,然后如果值发生变化,主机 Activity 将被触发,所以,要这样做,我简单地在我想要的 Fragment 处做一个 viewModel.setValue(personArray) .

问题

当我尝试在任何片段中实例化 SharedViewModel 时,我遇到了这个问题:

我试图断言!!对于 null,也使用 let,但它不起作用,我想知道它从哪里来 FragmentActivity required

如果我使用 viewLifecycleOwner 而不是 activity 它告诉我它不能用 FragmentFragmentActivity ?

有什么线索吗?

谢谢。

基本上,问题是在您的片段 class activity context 中将是 nullableViewModelPorviders 需要 Non-null 上下文 才能使用。

一个解决方案是让你的 ViewModel 对象 nullable (因为你的 activity 可以为 null) 里面您的片段如下所示:

var viewModel: SharedViewModel? = null

然后在初始化期间,

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

好的,我没看到

我在我的 Fragment 中创建了一个 viewModel 的实例,在我的 MainActivity 中创建了另一个实例,所以这样做,我们阻止观察者工作。

为了解决这个问题,我只是做了一个简单的方法,returns 我在 MainActivity

中创建的实例
 fun getViewModelInstance():SharedViewModel = viewModel

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

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

片段提供了一种检索 non-null Activity - requireActivity() 的辅助方法。使用它代替 activity:

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

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

val viewModel: SharedViewModel by activityViewModels()

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

ViewModelProviders.of() 是deprecated.So,我们可以像下面这样初始化viewmodel。

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