01 May 2019

Kotlin Coroutines

I don't by any means propose to be a master on this topic, but there's been so much chat on this topic on the blog world, I thought I'd give it a try. As is my usual I always like to start with the most insanely simple scenario I can think of.

I started off reading this article which actually gives a really nice overview of what coroutines are and why they're important:
https://medium.com/androiddevelopers/coroutines-on-android-part-i-getting-the-background-3e0e54d20bb

I started by creating a new Kotlin project, I'm on Android Studio 3.3.2 and Kotlin version 1.3.21 and added the following library:

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

Maybe this will be added into standard Kotlin in the future. For me this was quite a surprise
that it needed a separate library.

Now let's jump straight into some reckless coding, I added a TextView to my activity with the ID 

android:id="@+id/hello_world"
Now let's create a function that will run in the background. I'm thinking of this like the main thread on an AsyncTask. For my function, I'm going to pause for ten seconds and then return a string.

suspend fun get(): String {
    //Delay for ten seconds
    delay(10000)
    return "All your base are belong to me"
}
Now a plain vanilla function to show the results
fun show(result: String) {
    val tv = findViewById<TextView>(R.id.hello_world)
    tv.setText(result)
    println("Done!")
}
Now we need to setup the Activity to allow for Coroutines. This in my opinion is a bit of a mess. I've no idea why I need all this boilerplate nonsense. Oh well
class MainActivity : AppCompatActivity(), CoroutineScope {

    private var job: Job = Job()

    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job

    override fun onDestroy() {
        super.onDestroy()
        job.cancel()
    }
You'll see we need to implement the CoroutineScope and add some other fluff just to use Coroutines. Lastly we can call our function in the background from our onCreate method

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    launch {
        // Dispatchers.IO
        val result = get()
        // Dispatchers.Main
        show(result)
    }

    println("Start!")
}
So as you can see onCreate launches get in the background which waits ten seconds then returns a string. The launch method then, (when complete) calls the show method with that result. I know that's an incredibly basic example but I hope it helps. I found the concept easy to grasp, but the implementation was a bit fiddly. Hence the blog post.