延迟后 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
无法在线执行。由于 lifecycleScope
由 Dispatchers.Main
调用必须延迟到下一个 ui 线程周期,在此期间片段已经处于 STARTED
状态,因此您的观察者处于活动状态并且它接收每个实时更新。
这是我的代码:
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
无法在线执行。由于 lifecycleScope
由 Dispatchers.Main
调用必须延迟到下一个 ui 线程周期,在此期间片段已经处于 STARTED
状态,因此您的观察者处于活动状态并且它接收每个实时更新。