ถ้าพูดถึง Task บนแอนดรอยด์ นักพัฒนาหลาย ๆ คนอาจจะไม่ค่อยคุ้นเคยกันมากนัก เพราะ Task ก็เป็นอีกอย่างหนึ่งที่ไม่ได้ส่งผลต่อการพัฒนาแอปโดยตรง แต่จะอยู่ในเบื้องหลังเพื่อทำให้แอปทำงานตามที่ระบบแอนดรอยด์ได้ออกแบบไว้
บทความในชุดนี้
- ตอนที่ 1 - Introduction
- ตอนที่ 2 - Back Stack
- ตอนที่ 3 - Task [Now Reading]
- ตอนที่ 4 - Home Screen และ Recents Screen
- ตอนที่ 5 - Activity Launch Mode [1/2]
- ตอนที่ 6 - Activity Launch Mode [2/2]
- ตอนที่ 7 - Task Affinity
- ตอนที่ 8 - Multiple Task และ Concurrent Document
Task กับการทำงานของระบบแอนดรอยด์
Task คือสิ่งที่ระบบแอนดรอยด์สร้างขึ้นมาทุกครั้งเมื่อผู้ใช้กดเปิดแอปจาก Home Screen โดย Activity และ Activity Stack ที่พูดถึงในบทความก่อนหน้านี้ก็จะอยู่ใน Task อีกทีนั่นเอง
ถ้าดูจากภาพข้างบนจะเห็นว่าแอป 1 ตัวจะมี Task อยู่ข้างใน และสามารถมี Multiple Task ได้ด้วย แต่โดยทั่วไปแล้วถ้านักพัฒนาไม่ได้ทำกับ Task เป็นพิเศษ ดังนั้นแอป 1 ตัวมักจะมีเพียง 1 Task เท่านั้น
และ Task จะมีอยู่ด้วยกัน 2 สถานะคือ Foreground และ Background โดยที่
- เป็น Foreground เมื่อผู้ใช้เปิดแอปขึ้นมาบนหน้าจอ (Activity ของ Task แสดงอยู่บน)
- เป็น Background เมื่อผู้ใช้ย่อแอปไป Home Screen หรือสลับไปใช้งานแอปอื่น
และการทำงานของ Activity Lifecycle ส่วนหนึ่งก็มาจากตอนที่ Task เปลี่ยนสถานะระหว่าง Foreground กับ Background ด้วยเช่นกัน
- Task เปลี่ยนจาก Foreground เป็น Background - Activity จะเปลี่ยนสถานะไปเป็น
onPause
และonStop
ตามลำดับ - Task เปลี่ยนจาก Background เป็น Foreground - Activity จะเปลี่ยน Lifecycle ไปเป็น
onCreate
(ถ้า Activity ถูกทำลายเพื่อคืน Memory ในก่อนหน้านั้น),onStart
และonResume
ตามลำดับ
นอกจากนี้ นักพัฒนาสามารถใช้คำสั่งใน ADB เพื่อดูได้ว่าในอุปกรณ์แอนดรอยด์มี Task อะไรที่กำลังทำงานอยู่บ้าง ตัวไหนที่เป็น Foreground และมีตัวไหนบ้างที่อยู่ใน Background
adb shell am stack list
Task กับการกดปุ่ม Back
โดยปกติแล้วเวลาที่ผู้ใช้กดปุ่ม Back ในตอนที่ Activity เหลือแค่ตัวสุดท้าย (หรือเรียกกันว่า Root Activity) มักจะเข้าใจกันว่าเป็นการปิดแอป แต่ทั้งนี้ขึ้นอยู่กับว่าเป็นแอนดรอยด์เวอร์ชันอะไรด้วย
- Android 11 หรือต่ำกว่า - คำสั่ง
finish()
ใน Activity จะถูกเรียก และ Task ก็จะถูกทำลายทิ้ง - Android 12 ขึ้นไป - คำสั่ง
finish()
ใน Activity จะไม่ถูกเรียก และจะย้าย Task ไปเป็น Background แทน
จะเห็นว่าบน Android 12 มีการปรับเปลี่ยนรูปแบบการทำงานของ Task ในตอนกดปุ่ม Back ใหม่ให้ต่างไปจากเดิม ไม่ต่างอะไรกับการกดปุ่ม Home ทั้งนี้ก็เพื่อให้ผู้ใช้กดเปิดแอปใหม่อีกครั้งแล้วแอปเริ่มทำงานได้ไวขึ้น (Warm State) จากเดิมที่ต้องเข้าสู่ขั้นตอนเริ่มทำงานใหม่ทั้งหมด (Cold State)
สำหรับแอปที่สร้าง Splash Screen เป็น Root Launcher Activity แล้วเปิดหน้าแรกของแอปพร้อมกับใช้คำสั่ง finish()
ถ้าเป็น Android 12 ขึ้นไป ผู้ใช้จะเห็น Splash Screen เฉพาะตอนที่เปิดแอปครั้งแรกสุดเท่านั้น เพราะการเปิดแอปครั้งถัดไปจะเปิดหน้าแรกของแอปขึ้นมาทันที
ดังนั้นแอปควร Save State ให้กับ Activity ตัวนั้นเพื่อรองรับการใช้งานบน Android 12 ขึ้นไปด้วย ตอนแอปเริ่มทำงานจาก Warm State จะได้ไม่เจอปัญหา State Loss และสามารถกลับมาทำงานต่อได้ทันที หรือไม่ก็ดักการกดปุ่ม Back ใน onBackPressed
เพื่อสั่งให้ทำลาย Activity ทิ้งไปเลย
Multiple Task และ Concurrent Document
อย่างที่บอกไปในตอนแรกว่าแอปทั่วไปมักจะมีแค่ 1 Task เท่านั้น ซึ่งเพียงพอต่อการทำงานของแอปอยู่แล้ว แต่สำหรับบางแอปก็อาจจะต้องการ Task มากกว่าหนึ่งตัวก็ได้เช่นกัน
และตั้งแต่ Android 5.0 Lollipop เป็นต้นมา นักพัฒนาสามารถสร้างแอปให้มีหลาย Task ได้สะดวกมากขึ้นด้วยรูปแบบการทำงานของ Task ที่เรียกว่า Document
สำหรับการสร้างแอปให้รองรับการทำงานแบบ Multiple Task หรือ Concurrent Document จะขอแยกเป็นบทความ Task และ Back Stack ตอนที่ 8 - Multiple Task และ Concurrent Document โดยบทความนี้ก็จะมีการพูดถึงอยู่บ้างเป็นบางส่วน
การทำงานของ Task บน Multi-window
Multi-window เป็นฟีเจอร์ที่ถูกเพิ่มเข้ามาใน Android 7.0 Nougat เพื่อให้ผู้ใช้สามารถเปิดแอปหลายตัวได้พร้อม ๆ กัน ไม่ว่าจะเป็นลักษณะของการแบ่งพื้นที่หน้าจอ หรือแสดงเป็นหน้าต่างลอย ๆ ก็ได้เช่นกัน
โดยแอปที่ทำงานอยู่บน Multi-window จะมองว่า 1 หน้าต่างคือ 1 Task จึงเป็นที่มาว่าทำไมแอปส่วนใหญ่ไม่สามารถเปิดพร้อม ๆ กันหลายหน้าต่างใน Multi-window ได้ เพราะว่าเป็น Single Task หรือมีแค่ 1 Task
นั่นหมายความถ้าต้องการให้แอปสามารถเปิดหลายหน้าต่างพร้อมกันได้ ก็จะต้องทำให้แอปสามารถสร้าง Task หรือ Document ตัวใหม่ขึ้นมาแบบเดียวกับที่แอป Google Chrome ทำนั่นเอง
กำหนดการทำงานของ Task ได้อย่างไรบ้าง ?
ต้องบอกก่อนว่านักพัฒนาไม่สามารถเข้าไปแก้ไขหรือปรับเปลี่ยนการทำงานของ Task ในแอปได้โดยตรง (เช่นเดียวกับ Activity Stack)
ที่ทำได้จะมีแค่การกำหนดรูปแบบในการทำงานของ Task เมื่อต้องการให้ Activity ใด ๆ แสดงขึ้นมาบนหน้าจอเท่านั้น โดยจะเรียกการกำหนดค่าดังกล่าวว่า "Activity Launch Mode"
การกำหนดค่าสำหรับ Activity Launch Mode จะเป็นการกำหนดค่าให้กับ Activity ไม่ใช่ Task ซึ่งจะมีอยู่ 2 วิธีด้วยกัน
- Attribute ของ Activity ใน Android Manifest
- Intent Flag ตอนที่สร้าง Intent ผ่านโค้ด Java หรือ Kotlin
โดยรูปแบบของ Activity Launcher Mode จะมีอยู่หลายรูปแบบ และในบางรูปแบบจะมีให้ใช้แค่ในบางวิธีเท่านั้น เพื่อให้นักพัฒนาสามารถกำหนดรูปแบบการทำงานของ Task ที่เฉพาะเจาะจงกับแอปในบางสถานการณ์ได้
สำหรับรายละเอียดเกี่ยวกับ Activity Launch Mode จะขอแยกเป็นบทความ Task และ Back Stack ตอนที่ 5 - Activity Launch Mode [1/2] กับ ตอนที่ 6 - Activity Launch Mode [2/2]
สรุป
ถึงแม้ว่า Task จะไม่ได้ส่งผลกับการพัฒนาแอปโดยตรง แต่จะเห็นว่าการทำงานของระบบแอนดรอยด์บางอย่างนั้นมี Task อยู่เบื้องหลังด้วย ดังนั้นสำหรับการทำงานที่มีรูปแบบเฉพาะเจาะจง ก็อาจจะต้องทำความเข้าใจเกี่ยวกับการทำงานของ Task ด้วย
และนอกจากนี้นักพัฒนาสามารถกำหนดรูปแบบการทำงานของ Task สำหรับ Activity แต่ละตัวได้ด้วย รวมไปถึงการทำแอปให้รองรับกับ Multiple Task แต่เนื้อหาทั้งหมดนี้มีรายละเอียดเยอะพอสมควร เจ้าของบล็อกจึงขอแยกเป็นคนละบทความแทน