Migrating to Android Kotlin 1.3 Coroutines

Edit module build.gradle.

dependencies {
    // https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md
    def kotlin_version = '1.3.11'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

    // https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-android
    // implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.24.0'
    // implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.27.0-eap13'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.0'
}

Edit gradle.properties to remove kotlin.coroutines=enable.

# kotlin.coroutines=enable

Change import from

import kotlinx.coroutines.experimental.android.UIimport kotlinx.coroutines.experimental.launch

to

import kotlinx.coroutines.Dispatchersimport kotlinx.coroutines.GlobalScope

Replace code

launch(UI) {}launch(CommonPool) {}

to

// Main/UI ThreadGlobalScope.launch(Dispatchers.Main) {}// Background ThreadGlobalScope.launch(Dispatchers.Default) { // or Dispatchers.IO}

CoroutineScope should be implemented on entities with well-defined lifecycle that are responsible for launching children coroutines. Example of such entity on Android is Activity.

class MyActivity : AppCompatActivity(), CoroutineScope {    lateinit var job: Job    override val coroutineContext: CoroutineContext        get() = Dispatchers.Main + job    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        job = Job()    }    override fun onDestroy() {        super.onDestroy()        job.cancel() // Cancel job on activity destroy. After destroy all children jobs will be cancelled automatically    }    /*     * Note how coroutine builders are scoped: if activity is destroyed or any of the launched coroutines     * in this method throws an exception, then all nested coroutines are cancelled.     */    fun loadDataFromUI() = launch { // <- extension on current activity, launched in the main thread           val ioData = async(Dispatchers.IO) { // <- extension on launch scope, launched in IO dispatcher               // blocking I/O operation           }           // do something else concurrently with I/O           val data = ioData.await() // wait for result of I/O           draw(data) // can draw in the main thread        }    }}

NOTE: Refer to latest CoroutineScope implementation.

NOTE: For ViewModel CoroutineScope, cancel the job at onCleared.

If you are using retrofit2 kotlin coroutine adapter, you will bump into the following error.

java.lang.NoClassDefFoundError: Failed resolution of: Lkotlinx/coroutines/experimental/Deferred;
    at com.jakewharton.retrofit2.adapter.kotlin.coroutines.experimental.CoroutineCallAdapterFactory.get(CoroutineCallAdapterFactory.kt:59)

Replace the dependencies

// implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-experimental-adapter:1.0.0'
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'

References:

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.