问题
This is what I'm trying to do.
- Set an
ArrayList
of object inside a Fragment - Get that array from an observer within the
FragmentActivity
container (the activity that hosts all the fragments)
So, What I have done is the following.
First I created the SharedViewModel
from where I will set and get the data from :
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
}
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.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 .
The Problem
When I try to instantiate the SharedViewModel
inside any fragment I get this problem :
I tried to assert !! for the null, use let too, but is not working and I wonder from where it comes that FragmentActivity
required
If I use viewLifecycleOwner
instead of activity
it says to me that it cant be called either with Fragment or FragmentActivity ?
Any clues?
Thanks .
回答1:
Fragments offer a helper method for retrieving a non-null Activity - requireActivity()
. Use that instead of 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:
val viewModel: SharedViewModel by activityViewModels()
回答2:
Basically, issue is that inside your fragment class activity context would be nullable and ViewModelPorviders
require Non-null context to work with.
One solution would be making your ViewModel
object nullable (because your activity is nullable) inside your fragment like something below:
var viewModel: SharedViewModel? = null
then during initialization,
viewModel = activity?.let { ViewModelProviders.of(it).get(SharedViewModel::class.java) }
回答3:
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.
To solve this, I just made a simple method that returns the instance that I made inside my MainActivity
fun getViewModelInstance():SharedViewModel = viewModel
Then I just call that instance from any Fragment to work with it
(activity as MainActivity).getViewModelInstance().setPersonArray(personArray)
回答4:
Put the thing in onActivityCreated() instead of onCreateView()... That will solve the issue of getActivity() nullable... Because according to the lifecycle of a fragment, onActivityCreated() is after onCreareView()... And the activity is created on the call of onActivityCreated()... So, the getActivity() will return the activity just created
来源:https://stackoverflow.com/questions/56811012/viewmodelproviders-is-not-working-inside-my-fragment