Lifecycle ของ Activity ใน Android
มนุษย์นั้นมีวงจรชีวิตที่ว่า มีเกิด แก่ เจ็บ แล้วก็ตายฉันใด Activity ใน Android ก็ฉันนั้น และมันเป็นพื้นฐานสำคัญที่นักพัฒนาแอนดรอยด์ต้องรู้ แต่ถ้าหากไม่เข้าใจมันล่ะก็เรื่องที่ง่ายจะกลายเป็นเรื่องยาก และสิ่งที่ตามมาไม่ส่งผลดีแน่ๆ
เมื่อไม่นานมานี่ในงาน Google IO 2017 ได้มี Section หนึ่งที่พูดเรื่อง Architecture Components ของ Android โดยมีจะมีเนื้อหาส่วนหนึ่งที่พูดเกี่ยวกับ Lifecycle ของ Activity ในแบบใหม่บอกได้เลยว่าโคตรคูล แต่ก่อนที่เราจะไปเรียนรู้สิ่งใหม่เจ้าของบล็อคขอพากลับมาย้อนดูวิธีแบบเดิมเพื่อเป็นการทบทวนความรู้กันก่อน นะครับ ✌️
[Flowchart] Lifecycle Activity
การทำงานจาก Flowchart จะเห็นได้ว่า Activity ได้กำเนิดที่ onCreate() แล้วดำเนินชีวิตมาเรื่อยๆ และต้องเจอเหตุการณ์ต่างๆ ที่ต้องผ่าน state โน้น นี นัน แต่พอเมื่อถึงอายุไขก็จะมาตายที่ onDestroy() พูดอะไรเนี่ย งง โว้ย!! เพราะถ้าจะให้ดูการทำงานตาม Flowchart ก็ยังนึกภาพตามไม่ค่อยออก งั้นเจ้าของบล็อคขอยกตัวอย่าง ดังนี้
กรณีที่ 1 ผู้ใช้เปิดเข้ามาใช้งานแอพแล้วในระหว่างที่แอพกำลังทำงานอยู่ แล้วผู้ใช้ทำการกด Back เพื่อออกจากแอพ
จะเห็นได้ว่าเมื่อผู้ใช้เปิดแอพขึ้นมา Activity ที่ถูกกำหนดให้ผู้ใช้เห็นจะถูกเปิดขึ้นมาและเริ่มทำงานจาก onCreate() → onStart() → onResume() ผู้ใช้ก็ใช้งานตามปกติสุขและเมื่อผู้กด Back เพื่อออกจากหน้านั้น Activitity นั้นก็จะถูกทำลายลงโดยจะเริ่มการทำงานที่ onPause() → onStop() และลมหายใจสุดท้ายจะหยุดอยู่ที่ onDestroy()
กรณีที่ 2 ในระหว่างที่แอพกำลังทำงานอยู่ผู้ใช้กดเปิดแอพตัวอื่นๆจาก Notification ต่อมาผู้ใช้กลับเข้ามายังแอพของเราอีกครั้ง สามารถจะแบ่งออกได้ สองแบบ คือ
- ระยะเวลาที่ Activity ถูกบังจากแอพอื่นโดยใช้ไม่เวลานาน
2. ระยะเวลาที่ Activity ถูกบดบังจากแอพอื่นโดยใช้เวลานาน
จะเห็นได้ว่าเมื่อ Activity ไม่ได้แสดงให้ผู้ใช้เห็นจะมีระยะเวลาเข้ามาเกี่ยวข้องในการเป็นสถานะจาก onPause() มาเป็น onStop() แต่จากการทดสอบระยะเวลาที่ว่านั้นมันไม่ได้นานขนาดที่ว่าเป็นนาทีน่ะ มันแค่ไม่กี่วินาทีเอง
กรณีที่ 3 ผู้ใช้กดปิดหรือล็อคหน้าจอในระหว่างที่แอพกำลังทำงานอยู่ ต่อมาผู้ใช้ได้ทำการปลดล็อคหน้าจอแล้วกลับมายังแอพของเราอีกครั้ง
กรณีที่ 4 ในระหว่างที่แอพกำลังทำงานอยู่ผู้ใช้กดปุ่ม Home เพื่อย่อแอพแล้วสลับไปใช้แอพอื่น(แอพของเราไม่ได้ถูกปิดตัวลง และยังทำงานอยู่) ต่อมาผู้ใช้กลับเข้ามายังแอพของเราอีกครั้ง
แต่ถ้าในกรณีที่ผู้ใช้สลับไปเล่นแอพอื่นหลายตัวหรือขณะนั้น Memory ของเครื่องไม่เพียงพอแอพที่ถูกย่อไว้จะถูกระบบทำการขอ Memory คืน เนื่องจากระบบต้องหน่วยความจำเพื่อไปใช้ในแอพที่กำลังทำงานอยู่ และเมื่อผู้ใช้สลับกลับมาที่แอพของเราก็จะเป็นแบบนี้
และในกรณีเลวร้ายที่สุดคือ Memory ไม่เหลือแม้แต่น้อย Activity ก็จะโดนฉีกทิ้งแล้วแล้วเริ่มทำงานใหม่โดยอัตโนมัติ 👍
กรณีที่ 5 ผู้ใช้เข้างานแอพแล้วในระหว่างที่แอพทำงานอยู่ผู้ใช้ได้ทำการพลิกจอ (ทำการหมุนจอ)
จากกรณีที่ 4 ทำใหรู้ว่า Activity สามารถตายได้ตลอดเวลา ทำให้เกิดคำถามที่ว่าถ้าสมมุติว่าผู้ใช้พิมพ์ข้อความอยู่ แล้วสลับไปเล่นแอพอื่นจนเพลินทำให้เมื่อขณะที่ผู้ใช้สลับกลับมายังแอพของเราไม่มี Memory เหลือแล้ว จึงเป็นสาเหตุที่ทำให้ Activity ถูกทำลายค่าทุกอย่างที่ผู้ใช้เคยพิมพ์ทิ้งไว้ก็จะหายสาบศูนย์ไปในอากาศ ผู้ใช้ก็ต้องพิมพ์ใหม่ใช่ไหม?
ตอบว่าใช่ครับและไม่ใช่กรณีที่ 4 เป็นกรณีเดียวนะ กรณีที่ 5 ก็เป็นด้วย ละถ้าเป็นแบบนี้จะมีวิธีการแก้ไขปัญหาอย่างไร? เราต้องทำการจัดการที่ onSaveInstanceState() กับ onRestoreInstanceState() ด้วย สามารถอ่านเพิ่มเติม ของพี่ Akexorcist ได้เลย
จากกรณีตัวอย่างที่เจ้าของบล็อคได้กล่าวไว้ข้างต้นเป็นแค่ส่วนหนึ่งที่อาจจะเกิดขึ้น ซึ่งทางทีมพัฒนาระบบปฎิบัติการแอนดรอยด์ก็ได้ออกแบบ Lifecycle ของ Activity ขึ้นมาเพื่อให้นักพัฒนามีการจัดการกับแอพในแต่ละสถานการณ์ได้ง่ายขึ้น ซึ่งจะเห็นว่าสถานะที่เกิดขึ้นมีทำงานกันเป็นลำดับ จึงทำให้สามารถแยกคำสั่งไว้ตามความเหมาะสมได้ เช่น onStart() มีคำสั่งให้ทำการงานบางอย่างเริ่มทำงาน และใน onStop() ก็ต้องใส่คำสั่งที่ว่าให้การทำงานนั้นหยุดทำงาน ยกตัวอย่างดังนี้
- การใช้งาน EvenBus หรือ BroadcastReceiver
จากตัวอย่างถ้าหากเรามีการ Register ไม่ว่าจะเป็น EvenBus หรือ Broadcast Receiver ก็ควรจะทำการ UnRegister ออกด้วยโดยยึดตาม Lifecycle ของ Activity ไปเลยจะได้ไม่ต้องมานั่งคิดว่าควร Register/UnRegister ที่ไหนดี
2. การเรียกใช้งาน Location เพื่อดึงงตำแหน่งของผู้ใช้
ถ้าหากมีเรียกใช้งาน Location แล้วไม่ได้ทำการยกเลิกการใช้งานมัน ผลที่ตามมานั้นรุนแรงมาก เพราะมันกินทรัพยากรของเครื่องเยอะจึงเป็นสาเหตุที่ก่อให้เกิดความเสียหาย ไม่ว่าจะเป็นอาการที่เครื่องจะร้อนจนเหมือนมันจะระเบิด 💥 แบตเตอรี่ลดลงไปรวดเร็วเหมือนเทน้ำทิ้ง และสุดท้ายแอพของเราก็จะถูกลบทิ้ง เพราะฉะนั้นควรจะทำให้การเรียกใช้งาน Location เป็นไปตาม Lifecycle ของ Activity :P
จากตัวอย่างจะเห็นได้ว่าเจ้าของบล็อคไม่ไปทำที่ onResume() กับ onPause() เลยเพราะว่าเจ้าของบล็อคชอบ onStart() กับ onStop() มากกว่าไม่มีอะไรมากหรอก
แล้วไปเอาไอ่พวก onStart(), onResume(), onPause(), onStop(), onRestart() และ onDestroy() มาจากไหนสร้างโปรเจ็คมาใหม่เห็นแค่ onCreate() ก็ให้ทำการ Override มันออกมาครับ Control+O หรือจะพิมพ์ตามชื่อเลยก็ได้นะครับเดียวมันขึ้นมาให้กด Enter เอง รูปร่างหน้าตาก็จะเป็นแบบนี้
ถ้าหากทั้งหมดที่เจ้าของบล็อคอธิบายมาผู้ที่ลงเข้ามาอ่านยังไม่เข้าใจก็แนะนำว่าให้นำโค้ดส่วนนี้ไป Run ดูครับ แล้วก็ลองทำตามกรณีที่เจ้าของบล็อคได้ยกตัวอย่างมาก็คิดว่าน่าจะช่วยให้นึกภาพออกมากขึ้น
สรุป
Activity Lifecycle ถือว่าเป็นอะไรที่สำคัญเอามากๆ นับว่าเป็นเรื่องพื้นฐานที่นักพัฒนาแอพฯแอนดรอยด์ต้องรู้ ถ้าหากใครยังไม่รู้จักอันนี้บาปเอามากๆ นะครับ เพราะมันทำให้โครงสร้างของโค้ดดูเป็นสัดส่วนไม่ใช่เอาไปยึดไว้ที่ onCreate() ให้หมดในที่เดียวเหมือนกับที่เจ้าของบล็อคเคยทำมา 😭 และมันก็ช่วยให้เราสามารถจัดการกับบางสถานการณ์ได้ง่ายขึ้น สิ่งที่สำคัญที่สุดก็คือเรื่องของการจัดการ การใช้งานทรัพยากรบนเครื่องที่มีอยู่อย่างจำกัดให้อยู่รอดปลอดภัย ก็หวังว่าบทความนี้จะเป็นประโยชน์ ส่วนเรื่อง Activity Lifecycle ตัวใหม่เอาไว้เจอกันในบทความหน้าแน่นอน ครับผม 👋