问题描述
我有一个Fragment A
,它显示项目列表。单击一个项目后,我们导航到Fragment B
,其中显示了所选项目的更详细视图。因此,我需要在Fragment A
和B
之间进行某种沟通。
在文档中(请参阅here),他们指出,建议使用共享的viewmodel
片段之间进行通信。因此,可以像这样实现它:
class Sharedviewmodel : viewmodel() {
// used to share Item between list and detail view
private val _selectedItem = mutablelivedata<Item>()
// Fragment B listens for this LiveData variable
val selectedItem : LiveData<Item> = _selectedItem
// called by the Fragment A which passes the selected item as argument
fun selectItem(item: Item) {
_selectedItem.value = item
}
}
在Fragment B
中,我们像这样监听selectedItem
LiveData变量:
....
// I use a global variable here cuz I want to use it in several different methods
private lateinit var selectedItem : Item
....
override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
super.onViewCreated(view,savedInstanceState)
// listen for the selected item
sharedviewmodel.selectedItem.observe(viewLifecycleOwner,Observer { item ->
selectedItem = item
})
}
现在,在onStart()
中,有些操作只能在初始化selectedItem
时进行:
override fun onStart() {
super.onStart()
doSomethingWithSelectedItem(selectedItem) //<--- CRASH
doAnotherThingWithSelectedItem(selectedItem) // probably it would crash here,too
}
这时,我得到一个例外,就是selectedItem
lateinit var变量未初始化。因此,我假设此时onViewCreated()
(即selectedItem = item
)中的设置尚未生效。
所以,我的问题是:当您要初始化一个Lateinit变量(该变量的值是通过viewmodel在两个Fragment之间共享的)时,哪种生命周期方法是最好的?
解决方法
我认为问题在于LiveData的watch()方法内部的函数没有立即执行。 OnViewCreated()是一种在onStart()之前执行的方法。如果LiveData Observe()方法立即执行该函数,则不会有任何问题。 watch()方法的作用是将LiveData对象设置为观察其值的更改,而无需立即执行定义的函数。
我要做的是在Fragment B
中编写这段代码:
override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
super.onViewCreated(view,savedInstanceState)
selectedItem = sharedViewModel.selectedItem.value
}
在您的情况下,我认为您甚至不需要使用LiveData对象,因为您只想获取一个值,并且只要您位于同一片段中,该值就不会更改。
,在onViewCreated()之前调用片段的onStart()生命周期 片段的生命周期。
在onstart中观察livedata并设置lateinit变量。并且取决于函数的作用,您可以在设置lateinit变量后在onStart()或onViewCreated()中调用它们