我是协程新手。所以我只想知道使用它们的最佳方法是什么。
我的场景/用例是我想在x
上进行API调用,并在IO thread
上观察结果并更新UI。同样,当调用片段的Main thread
时,我也想取消我的工作。
我的片段要求演示者进行一些更新。所以我的主持人有一个像这样的协程-
onDestoryView()
在我的存储库中,
class MyPresenter(view: MyView,
private val coroutineCtx: CoroutineContext = Dispatchers.Main) : CoroutineScope {
private val job: Job = Job()
private var view: MyView? = null
init {
this.view= view
}
override val coroutineContext: CoroutineContext
get() = job + coroutineCtx
fun updateData() = launch{
//repo is singleton
val scanResult = repo.updateData()
when(scanResult) {
sucess -> { this.view.showSuccess()}
}
}
fun stopUpdate() {
job.cancel()
}
}
我正确使用协程吗?如果是的话,尽管我从片段的suspend fun updateData(): Result<Void> {
val response = API.update().await()
return response
}
中调用它,但我的job.cancel()
似乎从未工作过。
答案 0 :(得分:0)
从我的角度来看,您正确使用了协程。一些注意事项:
您不必将view: MyView
传递给构造函数,并将其值分配给init
块中的属性。相反,您可以在构造函数中将view
参数标记为val
,它将成为属性:
class MyPresenter(private val view: MyView,
private val coroutineCtx: CoroutineContext = Dispatchers.Main) : CoroutineScope {
// you can get rid of the next lines:
private var view: MyView? = null
init {
this.view= view
}
}
launch
函数返回一个Job
。您可以添加扩展功能,例如launchSilent
,返回Unit
:
fun CoroutineScope.launchSilent(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
) {
launch(context, start, block)
}
根据我的观察,job.cancel()
正常工作:调用它时,协程必须停止。例如,如果我们放置一些日志:
fun updateData() = launch{
Log.d("Tag", "launch start")
val scanResult = repo.updateData()
when(scanResult) {
success -> { this.view.showSuccess()}
}
Log.d("Tag", "launch end")
}
并在仓库的updateData()
函数中添加一些延迟:
suspend fun updateData(): Result<Void> {
delay(5000)
val response = API.update().await()
return response
}
例如,在调用presenter.updateData()
之后的片段中,我们调用类似Handler().postDelayed({ presenter.stopUpdate() }, 3000)
的名称,我们不会在 Logcat中看到“启动结束” 。