รู้จัก Kotlin Coroutines ตั้งแต่ Zero จนเป็น Hero : ตอนที่ 1

ก่อนอื่นเรามารู้จักการทำงานของคอมพิวเตอร์กันก่อนดีกว่า
โดยปกติการเขียนโปรแกรมนั้นการที่เราสั่งให้คอมพิวเตอร์ทำงานโปรแกรมจะทำงานจากบรรทัดบน -> ลงบรรทัดล่างตามลำดับ

เดี๋ยวก่อน .. แหม่รีบจังเลยเรามาดูกันก่อนเราจะเรียนอะไรกันบ้างพร้อมแล้วเริ่มกันเล้ย

เนื้อหาที่คุณจะได้เรียนรู้ในบทความนี้

  • ข้อแตกต่างระหว่าง Synchronous และ Asynchronous
  • Coroutine คืออะไร แล้วทำไมมันมาเกี่ยวอะไรกับ Synchronous และ Asynchronous ได้ยังไง
  • Coroutine ไม่ใช้ได้ไหมแล้วเกิดอะไรขึ้น
  • Coroutine จะมาช่วยทำให้โค้ดอ่านง่ายขึ้นได้แค่ไหน ?
  • Suspend function
  • Coroutine builder , Scope , Context บลาาๆ

เอาล่ะเรามาเริ่มกันเลย

ข้อแตกต่างระหว่าง Synchronous และ Asynchronous

ต่อจากเมื่อกี้ .. แล้วจะเกิดอะไรขึ้นละเช่นถ้าบรรทัดที่สองเกิดทำงานนานสัก 20 วินาที แน่นอนว่ายังไม่ต้องไปถึงบรรทัดที่ 3 โปรแกรมก็หยุดรอสิครับ

ซึ่งการทำงานลักษณะนี้เราจะเรียกว่าการเขียนโปรแกรมแบบ Blocking programming คือโปรแกรมจะหยุดรอการทำงานจนกว่าจะทำงานเสร็จถึงจะทำงานบรรทัดถัดไป หรือเรียกอีกชื่อหนึงว่า การเขียนโปรแกรมแบบ Synchronous

แล้วเมื่อไรจะเข้าเรื่อง Coroutines สักที …… ใจเยนนนนนน ขอต่ออีกนิด

ต่อมามีคนมาบอกว่าาเฮ้ยย ไปรอทำไมละกว่าจะรอบรรทัดสองเสร็จ เสียเวลาเราก็ทำมันพร้อมกันไปซะเลยสิจะได้เสร็จไวๆ มันไม่ทำงานอะไรที่มันเกี่ยวข้องกันอยู่แล้วนิ ??

จนเป็นที่มาของ พ้ามม Asynchronous แล้วมันคืออะไรละแล้วมันทำงานยังไง
เอาละเล่าไปไม่เห็นภาพมาดูนี่กันเลยด้านบนจะเป็นการเขียนโปรแกรมแบบ
Synchronous ด้านล่างจะเป็น Asynchronous

Synchronous Programming
Asynchronous Programming

คือจะเห็นได้ว่าภาพด้านล่าง มันจะไม่สนใจเลยว่าบรรทัดก่อนหน้าตัวมันเองจะทำงานเสร็จแล้วหรือยังมันจะทำงานพร้อมกัน ซึ่งการเขียนโปรแกรมแบบนี้จะมีชื่อเรียกอีกแบบว่า Non-Blocking programming

Synchronous Programing (Blocking): การทำงานตามลำดับจนกระทั่งทำงานเสร็จสิ้น

Asynchronous Programing (Non-Blocking) : การทำงานอย่างไม่เป็นลำดับ โดยไม่คำนึงถึงว่าการทำงานลำดับก่อนหน้าเสร็จแล้วหรือไม่

หลังจากได้รู้จักความแตกต่างระหว่าง Synchronous และ Asynchronous Programing กันแล้วเรามาดูกันต่อว่ามันคืออะไรเกี่ยวอะไรยังไงกับ Coroutine

What is Coroutine

Coroutines = Co + Routines

Co มาจากคำว่า cooperation และ Routines นั้นหมายถึง functions
พอมารวมกันก็จะกลายเป็น ฟังก์ชันที่ทำงานร่วมกันกับฟังก์ชันอื่นๆ ซึ่งเราก็จะเรียกมันว่า Coroutine

จากภาพ Function A -> Function B -> Function C -> Function D เรียกกันต่อเนื่องกันไป จากนั้นจึง Call back กลับมา Function D -> Function A

บ่อยครั้งที่เราต้องมาเหนื่อยกับการเขียน Call Back มากมาย ซึ่ง Coroutine ถือเป็น Lightweight threads ตัวหนึ่งซึ่งการที่ coroutine เป็น Lightweight threads ทำให้เราสามารถเขียนโค้ดในรูปแบบ Asynchronous เขียนให้เป็นในรูปแบบ Synchronous ได้ เอาละเรามาเริ่มกันเลยย

Threads : หน่วยการทำงานย่อยของ Process

Lightweight threads : หน่วยการทำงานย่อยของ Threads

Your first coroutine with Hello world

เย้…ในที่สุดเราก็ Hello world ได้แล้ว ถ้าไม่มีอะไรผิดพลาดเราก็จะได้ผลลัพธ์หน้าตาเป็นแบบนี้

Hello,
World!

เห็นคำสั่งอะไรแว๊ปๆ ไหม

GlobalScope.launch

อดใจรอก่อนเดี่ยวเราจะเล่าให้ฟังว่ามันคือคำสั่งอะไร แต่อยากให้เห็นบรรทัด 9 มีคำสั่งให้ Thread Sleep ไป จะเกิดอะไรขึ้นละถ้ากำลังเลื่อนฟีดในหน้าจออย่างสนุกสนาน แอปจะค้างทันทีทันใด เนื่องจากเราไปสั่งการทำงานบน Main Thread

Why there is a need for Kotlin Coroutines?

ยังไม่เห็นภาพกันใช่ไหมเดี๋ยวเราจะมายกตัวอย่างที่เราเจอกันบ่อยๆ เช่น

  • การดึงข้อมูล Feed มาจาก Server
  • การนำข้อมูลที่ได้แสดง

จะเห็นว่าเมื่อเราใช้คำสั่งเรียก fetchAndShowFeedData จะไม่สามารถทำงานได้เกิดเหตุการ NetworkOnMainThreadException เนื่องจากตัวระบบปฏิบัติการไม่ยอมให้เราทำงานขณะที่แอปพลิเคชันกำลังทำงานบน Main Thread

ถึงแม้ว่าบางครั้งการทำงานอะไรบางอย่างที่นานๆ ตัวระบบปฏิบัติการยังยอมให้เราทำงานอยู่ก็ตามมันก็ไม่ใช่ความคิดที่ดีนัก เพราะบางครั้งอาจจะทำงานแอปพลิเคชันค้างไปเลยก็ได้ที่ทางที่ดี Process อะไรที่ทำงานบางอย่างนานๆ เราก็ควรจะพลักภาระให้ไปทำงานบน Background Thread ซะไม่พูดพล่ามทำเพลง ไปต่อกันเลยดีกว่า

การแก้ไขปัญหาที่ว่านี้มีหลากหลายวิธีไปดูแต่ละวิธีกันเล้ยย

  • ใช้ Call Back สิ เอิ่มม..ถ้า Call back เยอะๆ คงจะปวดหัวกันหน้าดู
fun fetchAndShowFeedData() {     
fetchFeedData { feedData ->
showFeedData(feedData)
}
}
  • ใช้ RxJava สิ ในโลกของ Reactive ด้วยวิธีนี้สามารถทำให้เราแก้ปัญหาความซับซ้อนของการ Call Back ได้
fetchFeedData().subscribeOn(Schedulers.io())               
.observerOn(AndroidSchedulers.mainThread())
.subscribe { feedData ->
showFeedData(feedData)
}
  • มาถึงพระเอกของเราใช้ Coroutines สิ
suspend fun fetchAndShowFeedData() {      
val feedData = fetchFeedData() // fetch on IO thread
showFeedData(feedData) // back on UI thread
}

สั้นๆ แค่นี้เลยหรอ ?? ใช่แล้วอ่านไม่ผิดหรอกแถมยังอ่านง่ายอีกต่างหาก

เห็นคำสั่งอะไรแว๊ปๆ ไหม

suspend fun

เดี๋ยวก่อนใจเย็นๆ ในบทความตอนต่อไปเราจะมาเล่าให้ฟังกันต่อว่าจริงๆ มันคือคำสั่งอะไรกันแน่ ??

เอาล่ะไปต่อตอนต่อไปกันเล้ย

สำหรับใครที่อดใจไม่ไหวเข้าไปอ่าน Doc กันก่อนได้เลยที่
Ref: https://kotlinlang.org/docs/reference/coroutines

--

--