ada*_*sha 3 android coroutine kotlin
我的应用程序中有一个类似于以下的代码
class MyFragment : Fragment(), CoroutineScope by MainScope() {
override fun onDestroy() {
cancel()
super.onDestroy()
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
doSomething()
}
private fun doSomething() = launch {
val data = withContext(Dispathers.IO) {
getData()
}
val pref = context!!.getSharedPreferences("mypref", MODE_PRIVATE)
pref.edit().putBoolean("done", true).apply()
}
}
Run Code Online (Sandbox Code Playgroud)
在生产中,我得到很多NPEs
的doSomething(
),而访问context
。
我的假设是coroutine
调用cancel()
in后被取消onDestroy()
,所以我没有费心检查context
空值。但看起来continues
即使在cancel()
被调用之后也能执行。我认为这会发生,如果cancel()
在完成后调用withContext
和恢复之前coroutines
。
所以我替换doSomething()
了以下内容。
private fun doSomething() = launch {
val data = withContext(Dispathers.IO) {
getData()
}
if (isActive) {
val pref = context!!.getSharedPreferences("mypref", MODE_PRIVATE)
pref.edit().putBoolean("done", true).apply()
}
}
Run Code Online (Sandbox Code Playgroud)
这修复了崩溃。
但是,这是预期的行为还是我做错了什么?Kotlin 的文档对此不是很清楚。而且网上的大部分例子都像我原来的代码。
withContext()
如果范围被取消,您的代码假定当它返回时将停止执行,但实际上它没有,直到kotlin 协程的1.3.0版。这是 GitHub问题。我猜您正在使用该库的早期版本。
我还建议您使用LifecycleScope而不是自定义范围。它是lifecycle-runtime-ktx
图书馆的一部分。因此,简化的解决方案如下所示:
// build.gradle
dependencies {
...
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0-rc02"
}
Run Code Online (Sandbox Code Playgroud)
class MyFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
doSomething()
}
private fun doSomething() = viewLifecycleOwner.lifecycleScope.launch {
val data = withContext(Dispathers.IO) {
getData()
}
val pref = context!!.getSharedPreferences("mypref", MODE_PRIVATE)
pref.edit().putBoolean("done", true).apply()
}
}
Run Code Online (Sandbox Code Playgroud)
还有其他有用的实用程序可以简化协程的使用,请查看使用 Kotlin 协程与架构组件文档部分。
归档时间: |
|
查看次数: |
2147 次 |
最近记录: |