Android Kotlin协同程序屏幕旋转
我正在启动一个协同程序,在指定的延迟后在屏幕上显示一个计数器值Android Kotlin协同程序屏幕旋转,android,kotlin,kotlinx.coroutines,Android,Kotlin,Kotlinx.coroutines,我正在启动一个协同程序,在指定的延迟后在屏幕上显示一个计数器值 job = launch(UI) { var count= 0 while (true) { textView.text = "${count++}" delay(200L) } } 现在,在屏幕旋转中,我希望用户界面不断得到正确计数器值的更新。是否有人知道如何在配置(如屏幕旋转)更改时恢复作业 默认情况下,旋转会终止活动并重新启动它。这意味着您的文本视图将不再
job = launch(UI) {
var count= 0
while (true) {
textView.text = "${count++}"
delay(200L)
}
}
现在,在屏幕旋转中,我希望用户界面不断得到正确计数器值的更新。是否有人知道如何在配置(如屏幕旋转)更改时恢复作业 默认情况下,旋转会终止活动并重新启动它。这意味着您的文本视图将不再是屏幕上的文本视图,而是属于旧活动的文本视图 你的选择是: 1) 将configSettings添加到清单以关闭此行为 2) 在活动重新启动时使用一些可以持久化的东西,如视图模型、加载程序、注入的事件总线等
就我个人而言,除非你有不同的纵向和横向布局,否则我只选择1号布局,它更容易。你可以在ViewModel中完成,而不是在Activity中 是否有人知道如何在配置(如屏幕旋转)更改时恢复作业 您的作业从未停止运行,但您一直保持并更新一个不再显示在屏幕上的
TextView
。配置更改后,您的活动及其整个视图层次结构将被删除
虽然从技术上讲,你可以配置你的应用程序,使其不在轮换时重新创建活动,但谷歌强烈反对你这样做。该应用程序似乎在轮换的情况下工作,但随后将在另一种配置更改(如时区、位置等)上中断。你只需咬紧牙关,让你的应用程序在活动娱乐活动中工作
我通过依赖我设置的a片段,使我的协同程序在活动娱乐中工作
retainInstance = true
这意味着您的片段实例在其父活动死亡后仍能生存,并且当新活动替换它时,Android会将您的片段注入其中,而不是创建一个新的片段。它不能阻止视图层次结构的破坏,您必须编写更新片段状态的代码来反映这些更改。它很有帮助,因为它允许您保持片段的状态,而不必费心进行打包
在配置更改时,您的片段将经历以下生命周期事件:
onDestroyView
onCreateView
它不会在暂停时执行onPause
/onResume
,只有在您切换活动或退出应用程序时才会执行此操作。您可以在onResume
中启动协作程序,并在onPause
中取消协作程序
从最近发布的kotlinx.coroutines
的0.23版开始,launch
成为一个扩展函数:您必须在控制生成作业生命周期的某些CoroutineScope
的上下文中调用它。您应该将其生命周期绑定到片段,因此让片段实现CoroutineScope
。另一个变化是,UI
coroutine上下文现在被弃用,取而代之的是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()
}
}
现在,随着视图层次结构的重建,您的协同程序将自动获取textView
的当前实例。如果在重建UI时,计时器滴答声恰好出现在不方便的时刻,则协同程序将自动跳过更新视图,并在下一滴答声时重试。我想我回答问题的方式是错误的。基本上,我的问题更多地与kotlin coroutine的工作重启有关。我可以存储作业本身并恢复它吗?您仍然需要一个存储作业的位置。