简体   繁体   English

ViewModelProviders 在我的 Fragment 中不起作用

[英]ViewModelProviders is not working inside my Fragment

This is what I'm trying to do.这就是我正在尝试做的。

  • Set an ArrayList of object inside a Fragment在片段内设置对象的ArrayList
  • Get that array from an observer within the FragmentActivity container (the activity that hosts all the fragments)FragmentActivity容器(承载所有片段的活动)中的观察者获取该数组

So, What I have done is the following.所以,我所做的是以下。

First I created the SharedViewModel from where I will set and get the data from :首先,我创建了SharedViewModel ,我将从中设置和获取数据:

SharedViewModel.kt共享视图模型.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

}

Now , I instantiate this ViewModel inside the MainActivity that hosts all the fragments creation, so , I can get the ArrayData from wherever Fragment its set :现在,我在承载所有片段创建的MainActivity中实例化这个ViewModel ,因此,我可以从任何 Fragment 集合中获取ArrayData

MainActivity.kt主活动.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)
        })
    }

}

Then the last thing I need to do is to set the value of that Array from whatever Fragment I want, and then the host Activity will be triggered if the value has changed, so, to do this, I simple do a viewModel.setValue(personArray) at my desired Fragment .然后我需要做的最后一件事是从我想要的任何 Fragment 设置该 Array 的值,然后如果该值发生更改,将触发主机 Activity,因此,为此,我简单地执行一个viewModel.setValue(personArray)在我想要的Fragment

The Problem问题

When I try to instantiate the SharedViewModel inside any fragment I get this problem :当我尝试在任何片段中实例化SharedViewModel我遇到了这个问题:

在此处输入图片说明

I tried to assert !!我试图断言!! for the null, use let too, but is not working and I wonder from where it comes that FragmentActivity required对于 null,也使用 let,但不起作用,我想知道FragmentActivity需要从哪里来

If I use viewLifecycleOwner instead of activity it says to me that it cant be called either with Fragment or FragmentActivity ?如果我使用viewLifecycleOwner而不是activity它告诉我它不能用FragmentFragmentActivity调用?

Any clues?有什么线索吗?

Thanks .谢谢 。

Fragments offer a helper method for retrieving a non-null Activity - requireActivity() . Fragment 提供了一种用于检索非空 Activity 的辅助方法 - requireActivity() Use that instead of activity :使用它代替activity

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

As an alternative, you can include the fragment-ktx dependency in your app and use the by activityViewModels() Kotlin property extension instead of using ViewModelProviders.of() at all:作为替代方案,您可以在您的应用程序中包含fragment-ktx依赖项,并使用by activityViewModels() Kotlin 属性扩展,而不是完全使用ViewModelProviders.of()

val viewModel: SharedViewModel by activityViewModels()

Ok, I was not seeing it好吧,我没看到

I was making an instance of the viewModel inside my Fragment , and another one, inside my MainActivity , so doing this, we prevent the observer to work.我在Fragment中创建了一个viewModel实例,在我的MainActivity 中创建了另一个实例,因此这样做可以防止观察者工作。

To solve this, I just made a simple method that returns the instance that I made inside my MainActivity为了解决这个问题,我做了一个简单的方法来返回我在MainActivity的实例

 fun getViewModelInstance():SharedViewModel = viewModel

Then I just call that instance from any Fragment to work with it然后我只需从任何 Fragment 调用该实例来使用它

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

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

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

Basically, issue is that inside your fragment class activity context would be nullable and ViewModelPorviders require Non-null context to work with.基本上,问题是在您的片段类活动上下文中可以为空,并且ViewModelPorviders需要使用非空上下文

One solution would be making your ViewModel object nullable (because your activity is nullable) inside your fragment like something below:一种解决方案在您的片段ViewModel您的ViewModel对象可以为(因为您的活动可以为空),如下所示:

var viewModel: SharedViewModel? = null

then during initialization,然后在初始化期间,

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM