As we know that asynchronous programming is very important for advance applications. because by the use of it we can increases amount of work that can be perform in parallel in the app. This allows you to run long running tasks away from the UI thread, in the background. By doing so, you avoid ANR problem like UI freezes, and provide a good experience for your users.
Android gives us several asynchronous programming mechanisms, but it’s hard to find the most appropriate one to use. Some mechanisms have a huge learning curve. Others require a lot of boilerplate code which we have to implement, and aren’t that concise. All of this affects the scalability of your app, and can increases the cognitive load for new developers. It would be best if the APIs you working on are easy to use.
Because all platforms on the JVM had the identical problem, the team from JetBrains has come up with a replacement API. the thought behind it’s to assist you solve of these problems, without a steep learning curve. during this tutorial, you’ll study that API – Kotlin Coroutines.
Why Use Coroutines?
As we know that, Android developers right now have many async tools to work. These may be RxJava/Kotlin/Android, AsyncTasks, Jobs, Threads, and many more. So the question will come why would you need another tool , something else to learn?
If you’ve worked with Rx, then you know that it takes a lot of effort to get to know it enough and to be able to use it safely. While AsyncTasks and Threads are responsible to easily introduce leaks and memory overhead. Finally, working on all these APIs, which use callbacks, can introduce lot of boiler code and the code can become unreadable, as you introduce more callbacks. So after trying with Kotlin Coroutines, you’ll know that they aren’t just another tool. They’re an another new way of thinking about asynchronicity!
Kotlin Coroutines help us to write asynchronous code in a more natural way.
Introduction to Coroutines
The documentation define that Kotlin Coroutines are like lightweight threads. they’re lightweight because when we create coroutines ,it doesn’t allocate new threads. They just use predefined thread pools, and smart scheduling for long task. Scheduling is that the process of determining which piece of labor you may execute next. rather like an everyday schedule.
Additionally, coroutines will be suspended and resumed mid-execution. this suggests you’ll be able to have a long-running task, which you’ll be able to execute little-by-little. you’ll pause it any number of times, and resume it when you’re ready again. we know this, creating an outsized number of Kotlin Coroutines would not allocate unnecessary memory overhead to your program. You’ll just suspend a number of them until the thread pool frees up.
Threads vs Coroutines
In any application to perform long running task we have to create worker thread and background thread. But creating more thread or background thread or worker thread is expensive have results in out of memory. In this context, to avoid such reasonably thing we use coroutines (as per the documentation) as “lightweight” threads. Usually, a coroutine is sitting on an actual thread pool, which is employed for background execution, and that is why it so effective. It only need the resources when it needs it. observe the subsequent code:
val jobs = List(100_000) {
launch {
delay(1000)
print(".")
}
}
jobs.forEach { it.join()
}
If you launch actual threads instead of coroutines the execution would take more time, and maybe wouldn’t even finish or freeze application and An OutOfMemoryException can easily occur with such a huge number of threads, but with coroutines, you will not face such kind of issue.
Why are solutions like Coroutines necessary?
Handling execution on multiple threads is a very complex task in modern application development. Drawing fancy loaders on the UI while expecting a network request is simply one simple example that you just cannot solve without writing asynchronous code. On a mobile OS like Android, the UI thread handles user interactions, like button clicks and swipe gestures, and also renders the layout itself. These are the basics; let’s take a glance at an example! After clicking a button, the appliance downloads JSON data from the network, deserializes it, and updates the layout with the results. (Deserialization and network communication are usually handled by some clever libraries to form the developers’ life easier, except for demonstration purposes, let’s keep on with the instance.) How would you code it?
fun fetchUserString(userId: String): String {
// request user from network
// return user String
}
fun deserializeUser(userString: String): User {
// deserialize
// return User
}
button.setOnClickListener {
val userString = fetchUserString("1")
val user = deserializeUser(userString)
showUserData(user)
}
I think this is often the foremost natural (and native) way of providing an answer for the above-described task. But there are huge problems with it.
1. Starting a network request on the UI thread may be a bad idea (on Android it’s not even possible because your app will throw an unsightly NetworkOnMainThreadException) because network requests usually take about a minimum of half a second, during which the UI are frozen. No fancy loader animations, no scrolling, etc.
2. Deserializing may be a high CPU load operation, and may eat huge chunks from frame rendering. Basically, the result’s the identical as within the time.
How can we solve these problems? we want to dispatch our network call and deserialization to a background thread. Sounds easy, but what is the best thanks to implement it?
Solution 1: Callbacks
Let’s suppose we refactored our fetchUserString and deserializeUser functions to try work on a background thread. The program must continue the execution with showing the result on the UI after the dispatched work is completed. we will achieve this by providing callbacks for the worker functions like this:-
button.setOnClickListener
deserializeUser(userString) { user ->
showUserData(user)
">
}
}
The problem with this solution is that code starts to diminish readable because the function calls with callbacks increase. This phenomenon is named callback hell. We definitely want to avoid it.
Solution 2: Reactive approach
The reactive approach provides a much better way of writing code because rather than nesting functions into others it allows you to compose them:-
button.setOnClickListener .flatMap { userString ->
deserializeUser(userString)
">
.subscribe
}
Most folks are very satisfied with the reactive way (myself included), but we’ve to admit that the code continues to be aloof from how we originally wanted to write down it – it’s a touch more complex for the employment case. Is there no other thanks to express concurrency in code? there’s.
Solution 3: Coroutines
This is what the implementation would appear as if if we used Kotlin coroutines:-
button.setOnClickListener val user = deserializeUser(userString).await()
showUserData(user)
">
}
Conclusion
In this article we discuss what are Kotlin coroutine, why we should use them, why the are better from thread and many more. In the next topic we will discuss about function of kotlin coroutine , internal working of coroutine ,scope of coroutine and many more. Never forget to read next article about deep kotlin coroutine.