Android-通过共享的ViewModel

问题描述

我有一个Fragment A,它显示项目列表。单击一个项目后,我们导航到Fragment B,其中显示了所选项目的更详细视图。因此,我需要在Fragment AB之间进行某种沟通。

在文档中(请参阅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()中调用它们