DEV Community

Cover image for async && await In Kotlin-Coroutines
Saketh
Saketh

Posted on

async && await In Kotlin-Coroutines

Before Getting Started I Suggest You Understand What's Actually Coroutine Jobs Are, Which I Have Discussed In The Previous Blog. And Make Sure That You Have Included Coroutines Dependency If It's Not Included:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
Enter fullscreen mode Exit fullscreen mode

Case Scenario

  • You May Already Know That When You Have Implemented Respective Codeblock In Your Code It Will Execute Sequentially.

  • In Other Words, They'll Be Executed One-By-One By Default.

  • But In Few Cases, You May Need To Start The Execution Of Multiple Codeblocks At A Time Where Output || Result Timing May Vary.

  • In Those Case Scenario's You Need To Work Asynchronously With Your Respective Codeblock Which Means You Need To Start Those Codeblock's Execution At A Time.

Asynchronous = Running Multiple Codeblocks At A Time Where Result || Output Will Be Returned || Executed Later On.

Introduction To async

  • Now, As I Mentioned Earlier That If You Want To Start Executing At A Time Then You Should Work Asynchronously.

  • In Kotlin, We Have Something Known As async Which Is Of Type Deferred From Which We Can Build Our Respective Codeblock Asynchronously.

  • async Doesn't Return A Job Which Is Also A Coroutine Builder.

  • As You Can See Below That async Is Of Type Deferred:
    defferd.png
    deferred expand.png

Introduction To await

  • As I Mentioned Above That async Will Help You To Work Asynchronously But It May Stop Other Execution Too🤷🏼‍♂️.

  • To Avoid That And We'll Be Using await Method With async So That Remaining Codeblock Execution Will Be Normal.

In Other Words, await Ensures That The Execution Will Go Further Until The Function Is Executed Completely.

Use Case Scenario's

  • As You Can See That I Have Created 2 Suspend Functions Through IO Dispatcher:
private suspend fun apiCall1() {

}

private suspend fun apiCall2() {

}
Enter fullscreen mode Exit fullscreen mode
  • And I'll Be Delaying For 2 Seconds And Returning A String In Both Functions Respectively:
private suspend fun apiCall1(): String {
        delay(2000L)
        return "Html Is A Programming Language🤭"
    }

    private suspend fun apiCall2(): String {
        delay(2000L)
        return "Stay Safe😷"
    }
Enter fullscreen mode Exit fullscreen mode

Case 1

Code Without Asynchronous

  • I'll Implement These Both Suspend Functions In A Coroutine With GlobalScope And With launch Coroutine Builder Through IO Dispatcher:
GlobalScope.launch(Dispatchers.IO) {
   Log.d("async-await", apiCall1())
   Log.d("async-await", apiCall2())
}
Enter fullscreen mode Exit fullscreen mode
  • Now If You'll Launch The Application After Successful Build You'll Notice That It Takes 4 Seconds To Log Those Messages Which I Have Given.

  • It's Because apiCall1() And apiCall2() Suspend Functions Delays 2 Seconds Respectively Before Returning Those Values.

  • If You Want To Measure The Time Taken To Complete Those Executions We Have Few Classes || Methods. In My Case,

  • I'll Be Using measureTimeMillis{...} Which Returns Us The Time Taken To Complete The Execution Which We Have Implemented In That Particular Method || Class In Milliseconds Format.

  • You Can Use measureTimeMillis{...} In A Variable So That You Can Get The Duration Of That Execution:

val time = measureTimeMillis{
// Codeblock
}
Enter fullscreen mode Exit fullscreen mode
  • Now Let's Add Those Suspend Functions In time Variable In Order To Get The Time Taken To Complete The Execution.
GlobalScope.launch(Dispatchers.IO) {
  val time = measureTimeMillis {
              Log.d("async-await", apiCall1())
              Log.d("async-await", apiCall2())
       }
              Log.d("async-await", "Time Taken To Complete-> $time ms.")
}
Enter fullscreen mode Exit fullscreen mode
  • And As You Can See That It Took 4 Seconds To Complete:

without async and await.png

  • It's Because We Are Not Executing Our Code Asynchronously, So It Executes Sequentially By Default.

Case 2

Coding Asynchronously

  • Make Sure That You Have Added async{...} To Work Asynchronously.

  • Coding Asynchronously Doesn't Make Your Codeblock To Cook The Result Primarily, It Makes Sure That Your Particular Codeblock Will Be Executed Primarily Rather Than The Result || Output.

  • I'll Be Implementing Both Of The Suspend Functions In Two Different Variables With async In A Coroutine For Demonstration:

GlobalScope.launch(Dispatchers.IO) {
val apiCall1 = async { apiCall1()}
val apiCall2 = async { apiCall2() }
}
Enter fullscreen mode Exit fullscreen mode
Now, It's The Moment Of Truth🔥.
  • Let's Implement Our Above Code BLock Where We Are Working Asynchronously In measureTimeMillis{...} So That We Can Get The Duration Of The Execution.

  • And Make Sure That You Have Implemented await() Method With our Variables So That Remaining Codeblock [If Any] Execution Will Be Normal Without Any Problem(s):

GlobalScope.launch(Dispatchers.IO) {
       val apiCall1 = async { apiCall1()}
       val apiCall2 = async { apiCall2() }
       val time = measureTimeMillis {
        Log.d("async-await", apiCall1.await())
        Log.d("async-await", apiCall2.await())
}
        Log.d("async-await", "Time Taken To Complete-> $time ms.")
}
Enter fullscreen mode Exit fullscreen mode
  • And As You Can See That Both Of The Suspend Functions Are Executed Simultaneously, Which Means Execution Is Now Completed In 2 Seconds Itself:

async and await.png

  • Well, As You Can See That It Worked Asynchronously🤙🏼.

Tips [Kinda]

  • As I Mentioned Earlier That async Is Also A Coroutine Builder That Means You Can Use async Instead Of launch If You Want To Work Asynchronously. But The Example I Have Given Above Doesn't Make Sense If I Launch A Coroutine With async.

  • launch and async handle exceptions differently. Since async expects An Eventual Call To await, It Holds Exceptions And Rethrows Them As Part Of The await Call. This Means If You Use async To Start A New Coroutine From A Regular Function, You Might Silently Drop An Exception. These Dropped Exceptions won't appear In Your Crash Metrics or Be Noted In Logcat.

In Other Words,

  • Make Sure That You Are Handling async Properly Because If You Aren't Handling It Properly Errors May Occur.

Well, That's All For Now🙌

Bye🤗

Discussion (0)