คุณยังคงใช้ AsyncTask ในแอพ Android ของคุณหรือไม่? คุณคงไม่ควรจะเป็นอีกต่อไป ต่อไปนี้เป็นวิธีแทนที่ด้วย Coroutines ของ Kotlin
เป็นเวลานานมากใน Android หากคุณต้องการทำอะไรแบบอะซิงโครนัสเมื่อสร้างแอป คุณอาจใช้ AsyncTask AsyncTask เป็น API ในเฟรมเวิร์กของ Android ที่ทำให้การรันการดำเนินการในเบื้องหลังเป็นเรื่องง่าย (ish) และส่งคืนค่าเมื่อดำเนินการเสร็จแล้ว และนั่นก็สมเหตุสมผล AsyncTask ต่างจาก Coroutines ของ Kotlin ตรงที่มีมาระยะหนึ่งแล้วและมีการติดตั้งในตัว
อย่างไรก็ตาม ทั้งปรัชญาการออกแบบและการใช้งาน AsyncTask ค่อนข้างล้าสมัยในช่วงหลายปีที่ผ่านมา ด้วยเหตุนี้ Google จึงได้ เลิกใช้ AsyncTask API แล้ว. คุณยังคงสามารถใช้งานได้หากต้องการ แต่ Google ไม่แนะนำให้ทำเช่นนั้น โชคดีที่มีทางเลือกมากมายสำหรับ AsyncTask รวมถึงฟีเจอร์ของภาษา Kotlin — coroutines
Coroutines API ของ Kotlin เป็นเฟรมเวิร์กที่ทรงพลังอย่างเหลือเชื่อ ซึ่งช่วยให้คุณทำสิ่งต่างๆ ได้มากมาย บทความนี้เป็นเพียงการเริ่มต้นของสิ่งที่เป็นไปได้เท่านั้น เราจะพูดถึงพื้นฐานที่จำเป็นในการย้ายจาก AsyncTask ไปยัง Coroutines
การเพิ่มการสนับสนุน Coroutines
ก่อนที่คุณจะเริ่มใช้ coroutines ได้ คุณต้องเพิ่มมันลงในโปรเจ็กต์ของคุณเสียก่อน
การเพิ่มการสนับสนุน Kotlin
หากคุณได้ติดตั้ง Kotlin ไว้แล้ว ให้ข้ามไปยังส่วนถัดไป มิฉะนั้น คุณจะต้องเพิ่มการรองรับ Kotlin ให้กับโปรเจ็กต์ของคุณ ดูบทช่วยสอนของฉันเกี่ยวกับการเพิ่ม Kotlin ให้กับโปรเจ็กต์ที่มีอยู่เพื่อดูรายละเอียดเพิ่มเติม
การเพิ่มไลบรารี Coroutine
ในระดับโมดูลของคุณ build.gradle
รวมถึงการอ้างอิงต่อไปนี้
dependencies {
...
implementation 'org.jetbrains.kotlinx: kotlinx-coroutines-core: 1.5.0'
implementation 'org.jetbrains.kotlinx: kotlinx-coroutines-android: 1.5.0'
}
ซิงค์โปรเจ็กต์ของคุณ จากนั้น Coroutines ของ Kotlin ก็พร้อมใช้งานแล้ว
การใช้โครูทีน
การใช้ CoroutineScope
หากต้องการใช้ Coroutine คุณจะต้องมีอินสแตนซ์ CoroutineScope ที่พร้อมใช้งาน วิธีง่ายๆ ในการทำเช่นนี้คือการนำไปใช้ในคลาสที่มีของคุณ
ตัวอย่างเช่น หากต้องการใช้ CoroutineScope ในกิจกรรม:
classSomeActivity : AppCompatActivity, CoroutineScope by MainScope() {
...
override fun onDestroy(){
super.onDestroy()
cancel()
}
}
สิ่งนี้จะทำให้ SomeActivity ใช้อินเทอร์เฟซ CoroutineScope โดยใช้คลาส MainScope MainScope จะจัดการตรรกะการใช้งานทั้งหมดสำหรับ CoroutineScope ในขณะที่ให้คุณใช้เมธอด CoroutineScope ได้ กำลังโทร cancel()
ใน onDestroy()
ตรวจสอบให้แน่ใจว่าไม่มีตรรกะอะซิงโครนัสทำงานต่อไปหลังจากออกจากกิจกรรมแล้ว
แทนที่ AsyncTask ด้วย Coroutines
สมมติว่าคุณมี AsyncTask อยู่ในกิจกรรมที่ดำเนินการระยะยาวในพื้นหลังและส่งคืนสตริงในที่สุด บางอย่างเช่นต่อไปนี้
private inner classSomeTask : AsyncTask
() {
override fun doInBackground(vararg params: Void): String {
try {
//Pretend this is an actual operation that takes 10 seconds and not just sleeping.
Thread.sleep(10000);
} catch (e: InterruptedException) {}
return"SomeString";
}
override fun onPostExecute(result: String) {
val someTextView = findViewById(R.id.some_text_view)
someTextView.text = result
}
}
การแทนที่สิ่งนี้ด้วยโครูทีนนั้นเป็นเรื่องง่าย เพียงแค่ใช้ async()
วิธี. คอตลิน async()
ทำงานบนเธรดใดก็ตามที่เปิดใช้งาน แต่ทำงานแบบอะซิงโครนัส ซึ่งหมายความว่าคุณสามารถอัปเดต Views ได้โดยไม่ต้องกังวลกับการใช้ Thread ที่ถูกต้อง
classSomeActivity : AppCompatActivity(), CoroutineScope by MainScope() {
...private fun doOperation(){
async {
//Inside coroutine scopes (like inside async here), delay is used instead of Thread.sleep.
delay(10000)
val someTextView = findViewById(R.id.some_text_view)
someTextView.text = "SomeString"
}
}
}
อย่างที่คุณเห็น การใช้ coroutines นั้นง่ายกว่าการใช้ AsyncTask มาก คุณไม่จำเป็นต้องเพียงแค่โทร async()
และปล่อยให้มันเป็นไปตามของมัน คุณสามารถเก็บการอ้างอิงไว้และรอให้เสร็จสิ้นได้
val asyncJob = async {
//Some operation
}
//Pause here until the async block is finished.
asyncJob.await()
//This won't run until asyncJob finishes, but other operations started before the job, or started from another method, can still run.
doSomethingElse()
ส่งคืนค่าด้วย async
คุณสามารถคืนค่าจาก async()
ถ้าคุณต้องการ. ตัวอย่างเดิมอาจเป็นแบบนี้
classSomeActivity : AppCompatActivity(), CoroutineScope by MainScope() {
...
private fun doOperation(){
val asyncJob = async {
//Inside coroutine scopes (like inside async here), delay is used instead of Thread.sleep.
delay(10000)//Whatever the type is of the last line is what async() eventually returns.
"SomeString"
}val result = asyncJob.await()
val someTextView = findViewById(R.id.some_text_view)
someTextView.text = result
}
}
การใช้ withContext
เพื่อความสะดวก Kotlin จัดให้ withContext()
. สิ่งนี้จะอินไลน์ทั้งหมด await()
สิ่งและเพียงแค่ส่งกลับค่าให้กับคุณ
classSomeActivity : AppCompatActivity(), CoroutineScope by MainScope() {
...
private fun doOperation(){
//Run asynchronously on the main Thread.
val result = withContext(Dispatchers.Main) {
delay(10000)"SomeResult"
}
val someTextView = findViewById(R.id.some_text_view)
someTextView.text = result
}
}
บทสรุป
ตัวอย่างข้างต้นเป็นเพียงการใช้งานเบื้องต้นของ Coroutines ของ Kotlin เพื่อช่วยคุณในการเริ่มต้น คุณไม่จำเป็นต้องจำกัดโครูทีนไว้ที่กิจกรรมหรือแม้แต่สิ่งใดก็ตามที่มีวงจรชีวิตที่เหมาะสม คุณสามารถเรียกใช้งานได้ทุกที่ นอกจากนี้ยังมีการดำเนินการขั้นสูงเพิ่มเติม เช่น การเลือกเธรดใดที่ควรรันตรรกะอะซิงโครนัส คู่มือนี้มีไว้เพื่อแสดงวิธีแทนที่ AsyncTask แบบธรรมดาด้วย Coroutine แบบธรรมดาเป็นหลัก
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการทำงานของ Coroutines และวิธีที่คุณสามารถใช้คุณสมบัติขั้นสูงเพิ่มเติมได้ โปรดดูที่ เอกสาร Kotlin อย่างเป็นทางการ.