LiveData 没有观察具有共享视图模型的子视图页面片段

Posted

技术标签:

【中文标题】LiveData 没有观察具有共享视图模型的子视图页面片段【英文标题】:LiveData is not observing on child viewpager fragments having a shared viewmodel 【发布时间】:2021-10-10 04:26:46 【问题描述】:

LiveData 不会观察子 viewpager 片段,其中子片段具有一个共享视图模型来访问数据。

这里 FragmentA 和 FragmentB 是 viewpager 的一部分,它们都共享一个 viemodel SharedViewModel。

public class SharedViewModel extends androidViewModel  //in Java

    private final MutableLiveData<Data> mLiveData = new MutableLiveData<>();
    public LiveData<Data> getLiveData() 
        return mLiveData;
    

    //for updating data through LiveData, using post as and when I get the response from DataSource as shown below.

    mLiveData.postValue(response); //getting the response on debugging

class FragmentA : Fragment()   //in Kotlin

    override fun onCreate(@Nullable savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        mViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
    

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View 
        ....

        mViewModel.liveData.observe(viewLifecycleOwner, 
            //no call coming in this block so unable to update view
        )
    

class FragmentB : Fragment()   //in Kotlin

    override fun onCreate(@Nullable savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        mViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
    

需要一些帮助来了解为什么实时数据无法观察到变化。

提前致谢。

【问题讨论】:

【参考方案1】:

您的 ViewModel 未共享。您已将其命名为 sharedViewmodel,但您通过传递 Unique Owner 获取它的实例的方式也将是一个 unique instance

共享视图模型的正确方式是

class SharedViewModel : ViewModel() 
    private val myLiveData = MutableLiveData<Data>()

    fun getMyLiveDta():LiveData 
      return myLiveData
    

现在在第一个片段中

class MasterFragment : Fragment() 

    private lateinit var itemSelector: Selector

    // Get instance of viewmodel in fragment like this
    private val model: SharedViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) 
        super.onViewCreated(view, savedInstanceState)
        
    

在这样的第二个片段中

class DetailFragment : Fragment() 

    private val model: SharedViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) 
        super.onViewCreated(view, savedInstanceState)
        model.selected.observe(viewLifecycleOwner, Observer<Item>  item ->
            // Update the UI
        )
    

【讨论】:

谢谢MRamzan。使用 ViewModel 初始化的活动范围有助于解决该问题。子片段是 viewpager 的一部分,它本身就是父片段的一部分。我可以有父片段范围而不是活动范围吗? 在您的父片段中,如果您使用 Activity 范围,您可能会遇到内存泄漏,因为在父 Activity 处于活动状态之前,您的 ViewModel 也将可用。 在观察嵌套片段中的数据时,使用 activity 或 getactivity() 代替 viewLifecycleOwner。

以上是关于LiveData 没有观察具有共享视图模型的子视图页面片段的主要内容,如果未能解决你的问题,请参考以下文章

LiveData,是不是可以观察特定值

Android LiveData防止在观察时接收到最后一个值

在 SwiftUI MVVM 中的子视图和父视图之间共享值

在 Android 视图模型中的内部网络更改回调时 LiveData 未触发 - Kotlin

在视图模型中使用 LiveData 的结果从 firebase 获取数据

如何在基础活动暂停时暂停rxjava Observable.interval