ในบางแอป การมีแค่ Task เดียวก็อาจจะไม่ตอบโจทย์การใช้งานได้ทุกรูปแบบ ทำให้ระบบแอนดรอยด์ออกแบบให้แอปสามารถมี Task ได้มากกว่าหนึ่งตัวหรือที่เรียกว่า Multiple Task
บทความในชุดนี้
- ตอนที่ 1 - Introduction
- ตอนที่ 2 - Back Stack
- ตอนที่ 3 - Task
- ตอนที่ 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 [Now Reading]
Multiple Task → Concurrent Documents
ถึงแม้ว่า Task มากกว่า 1 ตัวจะเรียก Multiple Task ก็ตาม แต่นักพัฒนาจะเรียกกันว่า Concurrent Documents ซึ่งเป็นชื่อที่แอนดรอยด์กำหนดขึ้นมาอย่างเป็นทางการนับตั้งแต่ Android 5.0 Lollipop ที่เริ่มรองรับ Multiple Task อย่างจริงจังมากขึ้น
สำหรับ Task ใด ๆ ก็ตามที่แอปต้องการสร้างแยกออกมาสำหรับการทำงานบางอย่าง ตามนิยามของ Concurrent Documents เราจะเรียก Task เหล่านั้นว่า Document ยกตัวอย่างเช่น
- สร้างบันทึกใหม่ - แอปจดบันทึก
- สร้างร่างจดหมาย - แอปอีเมล
- เปิดหน้าต่างใหม่ - แอป Web Browser
ดังนั้นเมื่อพูดถึง Task และ Document ในหัวข้อนี้จึงหมายถึงสิ่งเดียวกัน
Task บน Multi-window Mode
ในการใช้งานทั่วไปที่แอปแสดงเต็มหน้าจอ เมื่อมี Task ใหม่ถูกสร้างขึ้นมา ก็จะแสดงแทนที่ตัวเก่า โดยที่ Recents Screen จะแสดง Task แยกกันถึงแม้ว่าจะเป็นแอปตัวเดียวกัน
แต่การทำงานบน Multi-window Mode จะเห็นได้ชัดเจนว่าแอปแต่ละหน้าต่างคือ Task คนละตัวกัน ถึงแม้ว่าจะมาจากแอปตัวเดียวกันก็ตาม
Split-screen Mode
โหมดที่จะแบ่งหน้าจอออกเป็น 2 ส่วนและสามารถแสดง 2 แอปได้พร้อม ๆ กัน
- แอปที่มี Task เดียว จะแสดงได้แค่ที่ฝั่งใดฝั่งหนึ่งเท่านั้น
- แอปที่มีหลาย Task แต่ละ Task สามารถกำหนดให้แสดงผลที่คนละฝั่งหน้าจอได้ ทำให้เปิดแอปเดียวกันในหน้าจอทั้ง 2 ฝั่งได้ เพราะเป็นคนละ Task กัน
Freeform Mode
โหมดที่จะแบ่งแอปเป็นหน้าต่างแยกกันอย่างอิสระ ทำให้ผู้ใช้สามารถใช้งานหลายแอปได้พร้อมกัน
- แอปที่มี Task เดียว จะแสดงได้แค่หน้าต่างเดียวเท่านั้น
- แอปที่มีหลาย Task จะแสดงแต่ละ Task เป็นหน้าต่างที่แยกกันอย่างอิสระ ทำให้เวลาสร้าง Task ใหม่ จะเป็นการสร้างหน้าต่างใหม่ขึ้นมานั่นเอง
การสร้าง Task สำหรับ Concurrent Documents
สำหรับการสร้าง Task เพื่อให้แอปรองรับ Concurrent Documents จะมีอยู่ 2 วิธีด้วยกัน
- กำหนดผ่าน Attribute ของ Activity ใน Android Manifest
- กำหนดผ่าน Flag ของ Intent
กำหนดผ่าน Attribute ของ Activity ใน Android Manifest
นักพัฒนาสามารถกำหนด android:documentLaunchMode
ใน Android Manifest ให้กับ Activity ที่ต้องการให้ทำงานแบบ Concurrent Documents ได้เลย โดยจะมีค่าให้กำหนดทั้งหมด 4 แบบด้วยกัน
intoExisting
- ระบบแอนดรอยด์จะค้นหาก่อนว่ามี Task ใดที่มี Activity ดัวนั้นอยู่หรือไม่ ถ้าไม่มีก็จะสร้าง Task พร้อมกับ Activity ขึ้นมาใหม่ แต่ถ้ามีอยู่แล้วก็จะเคลียร์ Task และสั่งให้เริ่มทำงานใหม่อีกครั้ง ทำให้ Activity กลับมาทำงานโดยส่งข้อมูลผ่านonNewIntent
แทน
การทำงานของinfoExisting
จะเหมือนกับ Intent ที่กำหนดค่าFLAG_ACTIVITY_NEW_DOCUMENT
always
- ระบบแอนดรอยด์จะสร้าง Task และ Activity ขึ้นมาใหม่เสมอ ถึงแม้ว่าจะเคยสร้าง Activity ตัวนั้นไว้ใน Task อื่นมาก่อนก็ตาม
การทำงานของalways
จะเหมือนกับ Intent ที่กำหนดค่าFRAG_ACTIVITY_NEW_DOCUMENT
และFLAG_ACTIVITY_MULTIPLE_TASK
คู่กัน
never
- เป็นการบังคับให้ระบบแอนดรอยด์สร้าง Activity ขึ้นมาบน Task เดิมเสมอ ถึงแม้ว่าจะมีการกำหนด Flag อย่างFLAG_ACTIVITY_NEW_DOCUMENT
ก็ตามnone
- เป็นค่า Default ของ Activity ที่ระบบแอนดรอยด์จะสร้าง Task ขึ้นมาใหม่ก็ต่อเมื่อมีการกำหนดFLAG_ACTIVITY_NEW_TASK
เท่านั้นกำหนดผ่าน Flag ใน Intent
ดังนั้นในกรณีที่ต้องการสร้าง Activity บน Task ใหม่ตลอดก็ให้กำหนดด้วย always
แต่ถ้าอยากให้สร้างขึ้นมาแล้วใช้ตัวเดิมตลอดก็ให้ใช้ infoExisting
แทนนั่นเอง
กำหนดผ่าน Flag ของ Intent
สำหรับ Flag ของ Intent ที่เกี่ยวข้องกับการทำงานของ Concurrent Documents จะมีอยู่แค่ 3 ตัวด้วยกัน คือ FLAG_ACTIVITY_NEW_DOCUMENT
, FLAG_ACTIVITY_MULTIPLE_TASK
และ FLAG_ACTIVITY_LAUNCH_ADJACENT
FLAG_ACTIVITY_NEW_DOCUMENT
- ระบบแอนดรอยด์จะค้นหาก่อนว่ามี Task ใดที่มี Activity ตัวนั้นอยู่หรือไม่ ถ้าไม่มีก็จะสร้าง Task พร้อมกับ Activity ขึ้นมาใหม่ แต่ถ้ามีอยู่แล้วก็จะเคลียร์ Task และสั่งให้เริ่มทำงานใหม่อีกครั้ง ทำให้ Activity กลับมาทำงานโดยส่งข้อมูลผ่านonNewIntent
แทน
การทำงานจะเหมือนกับintoExisting
ของandroid:documentLaunchMode
FLAG_ACTIVITY_NEW_DOCUMENT
+FLAG_ACTIVITY_MULTIPLE_TASK
- ระบบแอนดรอยด์จะสร้าง Task และ Activity ขึ้นมาใหม่เสมอ ถึงแม้ว่าจะเคยสร้าง Activity ตัวนั้นไว้ใน Task อื่นมาก่อนก็ตาม
การทำงานจะเหมือนกับalways
ของandroid:documentLaunchMode
FLAG_ACTIVITY_LAUNCH_ADJACENT
- ใช้ร่วมกับFLAG_ACTIVITY_NEW_DOCUMENT
ใน Split-screen Mode ของ Multi-window Mode เพื่อให้ระบบแอนดรอยด์สร้าง Task ตัวใหม่ขึ้นมาที่อีกฝั่งของหน้าจอ
นักพัฒนาใช้วิธีไหนดี ?
การสั่งงานสำหรับ Concurrent Documents จะเหมือนกับเรื่อง Launch Mode ที่จะขึ้นอยู่กับว่านักพัฒนาต้องการแบบไหน เพราะแต่ละแอปก็จะมีรูปแบบในการใช้งานที่แตกต่างกันออกไป
ถ้าต้องการให้ Activity บางตัวรองรับ Concurrent Documents เสมอ การกำหนดค่าผ่าน android:documentLaunchMode
ก็จะมั่นใจได้ว่าการทำงานจะเป็นแบบเดียวกันเสมอ โดยไม่ต้องกำหนด Flag ใน Intent ให้เสียเวลา
แต่ถ้าแอปออกแบบมาให้ Activity นั้น ๆ สามารถอยู่บน Single Task หรือ Concurrent Documents ก็ได้ การกำหนดผ่าน Flag ของ Intent ก็จะมีความยืดหยุ่นมากกว่า
จัดการกับ Task ในแอปด้วย ActivityManager
สำหรับการทำงานแบบ Concurrent Documents ที่อาจจะทำให้การทำงานของ Task มีความซับซ้อนมากขึ้น นักพัฒนาสามารถใช้ ActivityManager เพื่อควบคุมการทำงานบางอย่างสำหรับ Task ที่มีอยู่ทั้งหมดในแอปได้
val context: Context = /* ... */
val activityManager: ActivityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val appTasks: List<ActivityManager.AppTask> = activityManager.appTasks
โดยจะมีคำสั่งอย่าง
finishAndRemoveTask()
เพื่อทำลาย Task นั้น ๆ ทิ้งmoveToFront()
เพื่อสั่งให้ Task นั้น ๆ เป็น Foreground Task- ฯลฯ
สามารถเข้าไปดูคำสั่งทั้งหมดของ AppTask ได้ที่ ActivityManager.AppTask [Android Developers]
เรื่องอื่น ๆ ที่ควรรู้
- ในการทำ Concurrent Documents ควรออกแบบ User Flow ให้มีความซับซ้อนน้อยที่สุดเท่าที่ทำได้ (เช่น การแยก Flow ของการทำงานที่ต้องแยก Task ให้ชัดเจนและจบในตัว) เพื่อลดโอกาสที่จะเกิด Behavior นอกเหนือจากที่ต้องการ
- นักพัฒนาสามารถกำหนดได้ว่าจะให้ Task ในแอปแสดงอยู่บน Recents Screen ได้สูงสุดกี่ Task โดยกำหนดผ่าน
android:maxRecents
ของ<application>
ใน Android Manifest สามารถกำหนดได้สูงสุดถึง 50 Task (25 Task สำหรับเครื่องที่มี RAM น้อย)