ViewModelProviders 在我的 Fragment 中不起作用
ViewModelProviders is not working inside my Fragment
这就是我想要做的。
- 在片段中设置
ArrayList
个对象
- 从
FragmentActivity
内的观察者处获取该数组
容器(承载所有片段的activity)
所以,我所做的如下。
首先,我创建了 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
它告诉我它不能用 Fragment 或 FragmentActivity ?
有什么线索吗?
谢谢。
基本上,问题是在您的片段 class activity context 中将是 nullable 和 ViewModelPorviders
需要 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)
这就是我想要做的。
- 在片段中设置
ArrayList
个对象 - 从
FragmentActivity
内的观察者处获取该数组 容器(承载所有片段的activity)
所以,我所做的如下。
首先,我创建了 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
它告诉我它不能用 Fragment 或 FragmentActivity ?
有什么线索吗?
谢谢。
基本上,问题是在您的片段 class activity context 中将是 nullable 和 ViewModelPorviders
需要 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)