如何将 Kotlin 从 1.2 迁移到 Kotlin 1.3.0,然后在演示函数中使用异步、UI 和 bg

How to migrate Kotlin from 1.2 to Kotlin 1.3.0 then using async, UI, and bg in a presenter function

我在 Kotlin 项目中使用 MVP 模式。我有一个演示者 class:

import com.google.gson.Gson
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.async
import org.jetbrains.anko.coroutines.experimental.bg

class TeamsPresenter(private val view: TeamsView,
                     private val apiRepository: ApiRepository,
                     private val gson: Gson
) {
    fun getTeamList(league: String?) {
        view.showLoading()

        async(UI){
            val data = bg {
                gson.fromJson(apiRepository
                    .doRequest(TheSportDBApi.getTeams(league)),
                    TeamResponse::class.java
                )
            }
            view.showTeamList(data.await().teams)
            view.hideLoading()
        }
    }   
}

这个演示者 class 在 Kotlin 1.2.71 上工作正常,但我无法在 Kotlin 1.3.0 上工作。

我更新了项目 build.gradle 中的 Kotlin 版本,删除了 "experimental coroutines" 并添加了 kotlin 协程核心依赖项:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0'

这是我当前的代码:

import com.google.gson.Gson

class TeamsPresenter(private val view: TeamsView,
                     private val apiRepository: ApiRepository,
                     private val gson: Gson
) {
    fun getTeamList(league: String?) {
        view.showLoading()

        async(UI){
            val data = bg {
                gson.fromJson(apiRepository
                    .doRequest(TheSportDBApi.getTeams(league)),
                    TeamResponse::class.java
                )
            }
            view.showTeamList(data.await().teams)
            view.hideLoading()
        }
    }
}

错误主要发生在异步、UI 和 bg 函数上:

unresolved reference: async
unresolved reference: UI
unresolved reference: bg

我怎样才能让它在 Kotlin 1.3.0 上运行?如有任何帮助,请提前致谢。

你必须使用 GlobalScope.launch 而不是 launch ,GlobalScope.async 而不是 async Dispatcher.main 而不是 UI

coroutineBasics

您的代码有几层问题:

  1. 您正在使用 async,但没有 await。您应该改用 launch
  2. 您正在使用 bg 的预协程工具,等同于 async
  3. 您在 bg 上立即 await,这意味着您应该使用 withContext(Default) 而不是
  4. (Kotlin 1.3 的新功能)你没有申请 structured concurrency

您的代码在 Kotlin 1.3 中应该是这样的:

fun CoroutineScope.getTeamList(league: String?) {
    view.showLoading()
    this.launch {
        val data = withContext(Dispatchers.IO) {
            gson.fromJson(apiRepository.doRequest(TheSportDBApi.getTeams(league)),
                    TeamResponse::class.java
            )
        }
        view.showTeamList(data.teams)
        view.hideLoading()
    }
}

您应该使用适合您情况的协程范围调用您的函数。一种典型的方法是将其绑定到您的 activity:

class MyActivity : AppCompatActivity(), CoroutineScope {
    lateinit var masterJob: Job
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + masterJob

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        masterJob = Job()
    }

    override fun onDestroy() {
        super.onDestroy()
        masterJob.cancel()
    }
}

同时添加

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'

这是一个修复方法(我不知道这是否是最好的方法):

import com.google.gson.Gson
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch

class TeamsPresenter(private val view: TeamsView,
                     private val apiRepository: ApiRepository,
                     private val gson: Gson
) {
    fun getTeamList(league: String?) {
        view.showLoading()
        CoroutineScope(Dispatchers.Main).launch {
            val data = async {
                gson.fromJson(apiRepository
                    .doRequest(TheSportDBApi.getTeams(league)),
                    TeamResponse::class.java
                )
            }
            view.showTeamList(data.await().teams)
            view.hideLoading()
        }
    }
}