我正在启动一个协程,在指定的延迟后在屏幕上显示一个计数器值。
job = launch(UI) {
var count= 0
while (true) {
textView.text = "${count++}"
delay(200L)
}
}
现在在屏幕旋转时,我希望 UI 不断更新正确的计数器值。有人知道如何在配置(例如屏幕旋转)更改时恢复工作吗?
最佳答案
Does someone has any idea how to resume the job on configuration(e.g. screen rotation) change.
您的工作从未停止运行,但您一直坚持并更新 TextView
不再显示在屏幕上。配置更改后,您的 Activity 及其整个 View 层次结构都被抓取了。
虽然从技术上讲,您可以将您的应用配置为不重新创建旋转 Activity ,但 Google 强烈建议您不要这样做。该应用程序似乎适用于旋转的情况,但随后会中断另一种配置更改,如时区、位置等。您只需要咬紧牙关,让您的应用程序在 Activity 娱乐事件中工作。
我依靠一个 Fragment
让我的协程跨 Activity 娱乐工作我在其中设置
retainInstance = true
这意味着您的 fragment 实例在其父 Activity 终止后仍然存在,并且当新 Activity 取代它时,Android 会将您的 fragment 注入(inject)其中而不是创建一个新的。它不会阻止 View 层次结构的破坏,您必须编写更新 fragment 状态的代码以反射(reflect)这些变化。它有帮助,因为它允许您保持 fragment 的状态,而不是为分割而烦恼。
在配置更改时,您的 fragment 将经历这些生命周期事件:
-
onDestroyView
-
onCreateView
它不会通过 onPause
/onResume
,这只会在您切换 Activity 或退出应用程序时发生。您可以在 onResume
中启动协程并在onPause
中取消.
截至最近发布的 0.23 版 kotlinx.coroutines
, launch
成为一个扩展函数:你必须在一些 CoroutineScope
的上下文中调用它它控制生成的作业的生命周期。你应该将它的生命周期绑定(bind)到 fragment ,所以让你的 fragment 实现 CoroutineScope
.另一个变化是 UI
协程上下文现在已弃用,取而代之的是 Dispatchers.Main
.
这里有一个简短的例子来证明我提到的所有要点:
class MyFragment : Fragment, CoroutineScope {
private var textView: TextView? = null
private var rootJob = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + rootJob
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
retainInstance = true
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
val rootView = inflater.inflate(R.layout.frag_id, container, false)
this.textView = rootView.findViewById(R.id.textview)
return rootView
}
override fun onDestroyView() {
this.textView = null
}
override fun onResume() {
this.launch {
var count = 0
while (true) {
textView?.text = "$count"
count++
delay(200L)
}
}
}
override fun onPause() {
rootJob.cancel()
rootJob = Job()
}
}
现在,随着 View 层次结构的重建,您的协程将自动获取 textView
的当前实例。 .如果在重建 UI 时一个不方便的时刻恰好发生计时器滴答,协程将静默地跳过更新 View 并在下一个滴答时重试。
关于Android Kotlin Coroutine 屏幕旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52348349/