[Android] สถาปัตยกรรมของแอนดรอยด์ ตอนที่ 1 : Life Cycle

Jedsada Tiwongvorakul
20Scoops CNX
Published in
2 min readJun 7, 2017

จากงาน Google IO 2017 ที่พึ่งผ่านมานักพัฒนาแอพแอนดรอยด์คงจะได้ยินคำว่า “Android Architecture Components” จนติดหู และคงมีคำถามว่ามันคืออะไร แล้วมีอะไรใหม่บ้าง? เอาล่ะงั้นเรามาทำความรู้จักไปพร้อมๆกัน ลุย!

Android Architecture Components คือ Collection Library ใหม่ที่เกิดขึ้นมาเพื่อช่วยในเรื่องของการออกแบบ, ทดสอบ และการบำรุงรักษา ของตัวแอพให้มีประสิทธิภาพมากขึ้นกว่าเดิม รวมถึงจะช่วยให้การพัฒนาแอพเป็นไปตามรูปแบบที่ถูกต้องได้ง่ายยิ่งขึ้น

Android Architecture Components แบ่งออกได้ 4 กลุ่มดังนี้

ในบทความนี้เจ้าของบล็อคจะขอพามาทำความรู้จัก และรวมถึงการใช้งานของเจ้า Handling Lifecycles ส่วนหัวข้ออื่นก็จะตามกันมาติดๆ … ม่ะ เข้าเรื่องกันสักที

Handling Lifecycles

ถ้าพูดถึงเรื่องของการจัดการกับ Life Cycle ของ Activity/Fragment นักพัฒนาแอพแอนดรอยด์คงรู้ดีว่ามันสำคัญมากแค่ไหน แต่ปัญหาที่เรามักจะเจอคือ มันค่อนข้างที่จะเข้าใจยาก และบ่อยครั้งที่ชุดคำสั่งต้องทำงานร่วมกับ Life Cycle เราก็ต้องยึดชุดคำสั่งพวกนั้นไว้ที่ Acyivity /Fragment ทำให้โค้ดมารวมตัวกันอยู่ที่เดียวทำให้เราทำการจัดการโค้ดยาก ซึ่งการ Handling Lifecycles ในแบบใหม่ทำเราสามารถแยกชุดคำสั่งเหล่านั้นออกไปและยังสามารถทำรวมกับ Lifecycle ได้อย่างสวยงาม

แต่ถ้าผู้ที่เข้ามาอ่านยังไม่เข้าใจการจัดการ Life Cycle ในแบบเดิมก็สามารถกลับไปทำความเข้าใจได้จากด้านล่างนี้เลย

การเรียกใช้งาน Location ใน Activity โดยจะเริ่มจากการขอ Permission การเข้าถึงตำแหน่งของผู้ใช้ และมีการเริ่ม/หยุด การใช้งานของ Location ตาม Lifecycle ของ Activity ซึ่งปกติเจ้าของบล็อคทำก็จะได้ดังนี้

โค้ดจากด้านบนจะเห็นได้ว่าทุกอย่างยึดไว้ใน Activity เพราะเจ้าของบล็อคต้องการให้เริ่ม/หยุด การทำงานของ Location เป็นไปตาม Lifecycle ของ Activity

คิดภาพตามถ้าใน Activity นี้มีการเรียกใช้งานอื่นที่ต้องทำงานรวมกับ Lifecycle ของ Activity ที่มากกว่า Location เช่น BroadcastReceiver, EventBus หรือจะเป็น Sensor ของเครื่องต่างๆ ใน onStart() ก็จะมีคำสั่งเรียกใช้งานเต็มไปหมด เช่นเดียวกันใน onStop() ก็จะมีคำสั่งยกเลิกการทำงานเหล่านั้น และรวมถึงโค้ดที่ต้องค่อยรับค่าต่างๆ ซึ่งส่งผลให้ใน Activity ของเราก็จะมีโค้ดเยอะมากมาย

และแล้วก็มาถึงพระเอกของงาน เรามาลองเรียกใช้งาน Location ที่ทำงานรวมกับ Lifecycle โดยจะมีการจัดการ Lifecycle ในแบบใหม่กันดูว่ามันจะเข้ามาแก้ปัญหาที่เราเจอยังไง เริ่มกันเลย!

ขั้นตอนแรกก็ต้องอันเชิญ Dependency เข้ามาในโปรเจ็คก่อน

compile 'android.arch.lifecycle:extensions:1.0.0-alpha1'
annotationProcessor 'android.arch.lifecycle:compiler:1.0.0-alpha1'

ขั้นตอนต่อมาให้สร้างคลาสขึ้นมาจัดการการทำงานของ Location ดังนี้

จะเห็นว่าคลาส MyLocation.java ของเจ้าของบล็อคได้มีการ implements คลาสที่ชื่อว่า LifecycleObserver ที่แปลกหูแปลกตาออกไป และถ้าสังเกตที่ Constructor ดีๆ ก็จะเห็นพารามิเตอร์ที่แปลกออกไปตัวหนึ่งเช่นกัน คือ Lifecycle งั้นมาทำความรู้จักกับมันสักหน่อยว่ามีหน้าที่อะไร และมาจากไหน

LifecycleObserver คือ คลาสที่สามารถสังเกตการณ์เหตุการณ์ต่างๆ ของ Lifecycle ได้โดยเราสามารถกำหนดเองได้ว่าชุดคำสั่งส่วนไหนทำงานที่เหตุการณ์ไหนเพื่อจัดการกับการเปลี่ยนแปลงของ Lifecycle ใน Activity หรือ Fragment

Lifecycle คือ เหตุการณ์ต่างๆ ที่เกิดขึ้นใน Activity หรือ Fragment และเมื่อคลาสใดๆก็ตาม ที่ต้องการยุ่งเกี่ยวกับ Lifecycle ก็มีตัวแปรเพื่อเอาไว้ไปจัดการ Lifecycle ตามใจชอบ จึงเป็นที่มาที่เจ้าของบล็อคได้ทำการโยนเข้ามาที่ Constructor และใช้คำสั่งที่ชื่อว่า addObserver(LifecycleObserver lifecycleObserver) เพื่อทำการสร้างชุดคำสั่งให้ทำงานตาม Lifecycle ได้ โดยที่คำสั่ง addObserver นั้นต้องทำการ implement คลาสที่ชื่อว่า LifecycleObserver และจากโค้ดตัวอย่างเจ้าของบล็อคได้ทำการ implement ไว้เรียบร้อยแล้ว

มาถึงการใช้งาน จากโค้ดตัวอย่างจะมีดึง Location เมื่อ Activity/Fragment ทำงานที่ onStart() จะต้องตรวจสอบโดยการประกาศผ่าน Annotation แบบนี้

เมื่อ Activity/Fragment ทำงานที่ onStop() ก็จะทำการหยุดดึง Location ก็จะได้ประมาณนี้

และสุดท้ายเมื่อใช้งานเสร็จแล้ว หรือ Activity/Fragment ทำงานที่ onDestroy() ก็ควรที่จะอยากให้เคลียร์ตัวเองทิ้ง ก็สามารถลบคลาสนั้นๆ ออกจากการสังเกตการณ์ (Observer) ได้ดังนี้

แถมยังสามารถ Check state ก่อนทำการทำงานบ้างอย่างได้อีกด้วย โคตรคูล 🙏

Event ที่ใช้ในการตรวจสอบ Lifecycle

  • ON_CREARE คือ ค่าที่ใช้เพื่อจับคู่เหตุการณ์ onCreate()
  • ON_START คือ ค่าที่ใช้เพื่อจับคู่เหตุการณ์ onStart()
  • ON_RESUME คือ ค่าที่ใช้เพื่อจับคู่เหตุการณ์ onResume()
  • ON_PAUSE คือ ค่าที่ใช้เพื่อจับคู่เหตุการณ์ onPause()
  • ON_STOP คือ ค่าที่ใช้เพื่อจับคู่เหตุการณ์ onStop()
  • ON_DESTROY คือ ค่าที่ใช้เพื่อจับคู่เหตุการณ์ onDestroy()
  • ON_ANY คือ ค่าที่ใช้เพื่อจับคู่เหตุการณ์ทั้งหมด

State ที่ใช้ในการตรวจสอบ Lifecycle

  • DESTROY คือ ค่าที่ตรวจสอบหลังจากผ่าน onDestroy()
  • INITIALIZED คือ ค่าที่ตรวจสอบหลังจาการสร้าง แต่ยังไม่ได้รับ (ตามความเข้าใจคือ อยู่ในช่วง onCreate())
  • CREATED คือ ค่าที่ตรวจสอบหลังจากผ่าน onCreate()
  • STARTED คือ ค่าที่ตรวจสอบหลังจากผ่าน onStart()
  • RESUME คือ ค่าที่ตรวจสอบหลังจากผ่าน onResume()

และในการที่เราเอา Lifecycle โยนเข้ามาให้คลาสที่ต้องยุ่งเกี่ยวกับ Lifecycle นั้นเอาก็จะเกิดคำถามว่า มาจากที่ไหนกันล่ะ? คำตอบคืด เอามาจาก Activity/Fragment/ Service ที่ยินยอมให้คลาสนั้นๆ คอยเฝ้าดูเหตุการณ์ของตน แต่มีขอแม้นิดหน่อยดังนี้

  • Activity ต้องสืบทอดมาจาก LifecycleActivity
  • Fragment ต้องสืบทอดมาจาก LifecycleFragment
  • Service ต้องสืบทอดมาจาก LifecycleService

เมื่อเราได้ทำการนำ LifecycleOwner เข้ามาช่วยเวลาเรียกใช้ MyLocationManager ใน Activity ก็จะทำการเรียกใช้เป็นแบบนี้แทน

จากโค้ดเจ้าของบล็อคใช้ Library ที่ชื่อว่า Dexter ในการขอ Permission และ MainActivity ก็สืบทอดมาจาก LifecycleActivity จึงสามารถโยน Lifecycle ให้กับคลาสที่ต้องการยุ่งเกี่ยวกับ Lifecycle ได้โดยผ่าน method ที่ชื่อว่า getLifecycle()

ดูเหมือนทุกอย่างจะราบเรียบ แต่เมื่อพบว่า LifecycleActivity นั้น สืบทอดมาจาก FragmentActivity แต่อยากเราใช้ AppCompatActivity เราต้องทำการ implement เอาเองแบบนี้

สรุป

ก็นับว่าเป็นอีกหนึ่ง Component ที่โคตรคูล เพราะสามารถทำให้โค้ดที่จะต้องยุ่งเกี่ยวกับ Lifecycle นั้นไม่ต้องมากองรวมกันเป็นภูเขาอยู่ใน onResume(), onStart(), onPause(), onStop() และ onDestroy() อีกต่อไป และการที่เราใช้ LifecycleObserver เข้ามาช่วยทำให้คลาสที่ต้องยุ่งเกียวกับ Lifecycle ไปทำการจัดการกันเอาเองเพียงแค่เราทำการประกาศ Annotation ของ Event หรือมีการตรวจสอบ State ของการทำงานว่าจะให้หลัง Activity/Fragment/Service ผ่าน State ไหนมาแล้วจึงจำเริ่มทำงาน ให้ถูกต้องก็พอ แล้วเอาไว้เจอกันกับ Android Architecture Components ตัวอื่นในบทความถัดไปนะครับ 👋

--

--