协程的最佳使用方式

时间:2019-03-09 23:58:03

标签: android kotlin kotlin-coroutines

我是协程新手。所以我只想知道使用它们的最佳方法是什么。

我的场景/用例是我想在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()似乎从未工作过。

1 个答案:

答案 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中看到“启动结束”