延迟后 LiveData 会发生什么

What happen with LiveData after delay

这是我的代码:

HomeFragment

...

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

    homeViewModel.myTest.observe(viewLifecycleOwner) {
        Log.d(TAG, "myTest=$it")
    }

    lifecycleScope.launch {
        homeViewModel.doSomethingForMyTest()
    }

}
...

HomeViewModel

...

private val _myTest = MutableLiveData<String>()
val myTest: LiveData<String> = _myTest

fun doSomethingForMyTest() {
    Log.i(TAG, "doSomethingForMyTest start: ${System.currentTimeMillis()}")
    (1..3).forEach {
        _myTest.value = it.toString()
    }
    Log.i(TAG, "doSomethingForMyTest end: ${System.currentTimeMillis()}")
}

...

log :

I/HomeViewModel: doSomethingForMyTest start: 1628586904976
I/HomeViewModel: doSomethingForMyTest end: 1628586904977
D/HomeFragment: myTest=3

如果在调用函数之前添加延迟,如下所示:

HomeFragment

...

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    homeViewModel.myTest.observe(viewLifecycleOwner) {
        Log.d(TAG, "myTest=$it")
    }
    lifecycleScope.launch {
        delay(1)
        homeViewModel.doSomethingForMyTest()
    }
}

...

log :

I/HomeViewModel: doSomethingForMyTest start: 1628587129413
D/HomeFragment: myTest=1
D/HomeFragment: myTest=2
D/HomeFragment: myTest=3
I/HomeViewModel: doSomethingForMyTest end: 1628587129414

如你所见,我不知道有什么区别...

为什么日志不同?

您缺少两件事:

viewLifecycleOwner - 在 onViewCreated 期间它仍处于 INITIALIZED 状态,因此您的 liveData 观察器将不会收到更新,直到片段移动到 STARTED 状态。

lifecycleScope - 它由 Dispatchers.Main.immediate 支持,这意味着当您已经处于正确的上下文(ui 线程)时 launch 会立即执行,直到第一次挂起打电话。

在第一种情况下,您添加了观察者,然后您的三个更新 运行 立即但观察者尚未激活,因此它仅在片段 viewLifecycleOwner 移动到 STARTED 状态时接收最后一个值。

在第二种情况下,delay 是一个暂停点,因此您的 launch 无法在线执行。由于 lifecycleScopeDispatchers.Main 调用必须延迟到下一个 ui 线程周期,在此期间片段已经处于 STARTED 状态,因此您的观察者处于活动状态并且它接收每个实时更新。