Kotlin 数据绑定共享视图模型不更新两个视图

Kotlin databinding shared viewmodel not updating both views

我正在尝试为 activity 和 activity 中显示的片段使用共享视图模型,因为两者都需要由视图模型更新。该片段使用 MutableLiveData 不断更新,但 activity 不是,我真的不明白为什么。出于可读性原因,我确实删除了 .xml 文件中与问题无关的布局参数。 我的 activity 代码如下所示:

class MainActivity : AppCompatActivity() {

     private lateinit var _binding : MainActivityBinding
     private val _viewModel : MySharedViewModel by viewModels()

     override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
         _binding = DataBindingUtil.setContentView(this, R.layout.main_activity)
         _binding.viewModel = _viewModel
         _binding.lifecycleOwner = this
         ...
     }
}

绑定的生命周期所有者已设置,但 MutableLiveData 似乎没有更新 activity。 在 activity 布局文件中如下:

<layout>
<data>
    <variable
        name="viewModel"
        type="com.customApp.viewModels.MySharedViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout>

    <com.google.android.material.appbar.MaterialToolbar>
        <TextView
            android:id="@+id/totalTime"
            android:text="@{viewModel.topBarText}"
            .../>
    </com.google.android.material.appbar.MaterialToolbar>

    <com.google.android.material.bottomnavigation.BottomNavigationView
    .../>

    <androidx.fragment.app.FragmentContainerView
    .../>

</androidx.constraintlayout.widget.ConstraintLayout>

所以我有顶部栏和始终显示文本的文本视图,底部导航视图作为选项卡栏和包含片段的片段容器视图。

片段代码为:

class FirstFragment : Fragment() {
    private val _viewModel : MySharedViewModel by viewModels()
    private lateinit var _binding : FirstFragmentBinding

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        _binding = DataBindingUtil.inflate(inflater, R.layout.first_fragment, container, false)
        _binding.viewModel = _viewModel
        _binding.lifecycleOwner = viewLifecycleOwner
        return _binding.root
    }
}

这里还为绑定设置了生命周期所有者,并且在片段布局中它绑定到视图模型:

<layout>
    <data>
        <variable
            name="viewModel"
            type="com.customApp.viewModels.MySharedViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout>
        <TextView
            ...
            android:text="@{viewModel.fragmentText}" />

        <Button
            android:id="@+id/startButton"
            android:onClick="@{() -> viewModel.startIteration()}"
            .../>

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

在我的视图模型中,我只是更新了应该显示的文本:

class MySharedViewModel : ViewModel() {
    var topBarText : MutableLiveData<String> = MutableLiveData<String>("Hi")
    var fragmentText : MutableLiveData<String> = MutableLiveData<String>("There")

    private val stringsForTop = arrayOf("Hi","How", "You")
    private val stringsForFragment = arrayOf("There","Are", "?")
    private var index = 0

    fun startIteration() {
        kotlin.concurrent.fixedRateTimer(initialDelay = 1L, period = 1000L) {
            viewModelScope.launch(Dispatchers.Main) {
                topBarText.value = stringsForTop[index]
                fragmentText.value = stringsForFragment[index]
                index++
            }
        }
    }
}

现在更新片段文本时,顶部栏中的文本不会更新,始终只显示“Hi”。我有一种感觉,当片段被初始化并且它的 viewLifecycleOwner 被绑定到视图模型时,视图模型的 activity 作为生命周期观察者被覆盖。 我是否遗漏了什么,或者是否有另一种方法可以在视图模型中注册 activity 和片段及其生命周期所有者?任何帮助表示赞赏。

如果您在 Fragment 中使用 by viewmodels<>(),它将创建 ViewModel 的新实例,并耦合到 Fragment 生命周期。如果您想要 ViewModelActivity 相同的实例由 activityViewModels<>() 使用,请在 Fragment

中尝试以下代码
private val _viewModel : MySharedViewModel by activityViewModels()