หลักพื้นฐานของ Android Kotlin 04.2: สถานการณ์วงจรที่ซับซ้อน

Codelab นี้เป็นส่วนหนึ่งของหลักสูตรหลักพื้นฐานของ Android Kotlin คุณจะได้รับประโยชน์สูงสุดจากหลักสูตรนี้หากทำตาม Codelab ตามลำดับ Codelab ของหลักสูตรทั้งหมดแสดงอยู่ในหน้า Landing Page ของ Codelab หลักพื้นฐานของ Android Kotlin

บทนำ

ใน Codelab ล่าสุด คุณได้เรียนรู้เกี่ยวกับวงจรของ Activity และ Fragment รวมถึงได้สำรวจเมธอดที่เรียกใช้เมื่อสถานะวงจรเปลี่ยนในกิจกรรมและ Fragment ในโค้ดแล็บนี้ คุณจะได้สำรวจวงจรของกิจกรรมโดยละเอียด นอกจากนี้ คุณยังจะได้เรียนรู้เกี่ยวกับไลบรารีวงจรของ Android Jetpack ซึ่งจะช่วยให้คุณจัดการเหตุการณ์วงจรด้วยโค้ดที่จัดระเบียบได้ดีขึ้นและดูแลรักษาง่ายขึ้น

สิ่งที่คุณควรทราบอยู่แล้ว

  • กิจกรรมคืออะไรและวิธีสร้างกิจกรรมในแอป
  • พื้นฐานของวงจรActivityและFragment รวมถึง Callback ที่เรียกใช้เมื่อกิจกรรมเปลี่ยนสถานะ
  • วิธีแทนที่เมธอดเรียกกลับวงจร onCreate() และ onStop() เพื่อดำเนินการในเวลาต่างๆ ในวงจรกิจกรรมหรือ Fragment

สิ่งที่คุณจะได้เรียนรู้

  • วิธีตั้งค่า เริ่มต้น และหยุดส่วนต่างๆ ของแอปในการเรียกกลับสำหรับวงจร
  • วิธีใช้ไลบรารีวงจรของ Android เพื่อสร้างเครื่องสังเกตการณ์วงจร และทำให้จัดการวงจรของกิจกรรมและ Fragment ได้ง่ายขึ้น
  • การปิดแอปโดย Android ส่งผลต่อข้อมูลในแอปอย่างไร รวมถึงวิธีบันทึกและกู้คืนข้อมูลนั้นโดยอัตโนมัติเมื่อ Android ปิดแอป
  • การหมุนอุปกรณ์และการเปลี่ยนแปลงการกำหนดค่าอื่นๆ ทำให้เกิดการเปลี่ยนแปลงสถานะวงจรชีวิตและส่งผลต่อสถานะของแอปอย่างไร

สิ่งที่คุณต้องทำ

  • แก้ไขแอป DessertClicker ให้มีฟังก์ชันตัวจับเวลา แล้วเริ่มและหยุดตัวจับเวลาดังกล่าวในเวลาต่างๆ ในวงจรของกิจกรรม
  • แก้ไขแอปให้ใช้ไลบรารีวงจรของ Android และแปลงคลาส DessertTimer เป็นเครื่องสังเกตวงจร
  • ตั้งค่าและใช้ Android Debug Bridge (adb) เพื่อจำลองการปิดกระบวนการของแอปและการเรียกกลับวงจรของแอปที่เกิดขึ้น
  • ใช้เมธอด onSaveInstanceState() เพื่อเก็บรักษาข้อมูลแอปที่อาจสูญหายหากแอปปิดโดยไม่คาดคิด เพิ่มโค้ดเพื่อกู้คืนข้อมูลดังกล่าวเมื่อแอปเริ่มทำงานอีกครั้ง

ใน Codelab นี้ คุณจะได้ขยายแอป DessertClicker จาก Codelab ก่อนหน้า คุณเพิ่มตัวจับเวลาพื้นหลัง แล้วแปลงแอปให้ใช้ไลบรารีวงจรของ Android

ใน Codelab ก่อนหน้า คุณได้เรียนรู้วิธีสังเกตวงจรของกิจกรรมและ Fragment โดยการลบล้างการเรียกกลับของวงจรต่างๆ และบันทึกเมื่อระบบเรียกใช้การเรียกกลับเหล่านั้น ในงานนี้ คุณจะได้ดูตัวอย่างที่ซับซ้อนมากขึ้นในการจัดการงานวงจรของแอป DessertClicker โดยคุณจะใช้ตัวนับเวลาที่พิมพ์ข้อความบันทึกทุกวินาที พร้อมจำนวนวินาทีที่ตัวนับเวลาทำงาน

ขั้นตอนที่ 1: ตั้งค่า DessertTimer

  1. เปิดแอป DessertClicker จากโค้ดแล็บล่าสุด (คุณดาวน์โหลด DessertClickerLogs ได้ที่นี่หากไม่มีแอป)
  2. ในมุมมองโปรเจ็กต์ ให้ขยาย java > com.example.android.dessertclicker แล้วเปิด DessertTimer.kt โปรดทราบว่าขณะนี้โค้ดทั้งหมดถูกแสดงความคิดเห็นไว้ จึงไม่ได้ทำงานเป็นส่วนหนึ่งของแอป
  3. เลือกโค้ดทั้งหมดในหน้าต่างเอดิเตอร์ เลือกโค้ด > แสดงความคิดเห็นด้วยความคิดเห็นบรรทัด หรือกด Control+/ (Command+/ ใน Mac) คำสั่งนี้จะยกเลิกการแสดงความคิดเห็นในโค้ดทั้งหมดในไฟล์ (Android Studio อาจแสดงข้อผิดพลาดในการอ้างอิงที่ยังไม่ได้รับการแก้ไขจนกว่าคุณจะสร้างแอปใหม่)
  4. โปรดทราบว่าคลาส DessertTimer มี startTimer() และ stopTimer() ซึ่งจะเริ่มและหยุดตัวจับเวลา เมื่อ startTimer() ทำงาน ตัวจับเวลาจะพิมพ์ข้อความบันทึกทุกวินาที โดยมีจำนวนวินาทีทั้งหมดที่ตัวจับเวลาทำงาน ส่วนstopTimer() method จะหยุดตัวจับเวลาและข้อความบันทึก
  1. เปิด MainActivity.kt ที่ด้านบนของคลาส ใต้ตัวแปร dessertsSold ให้เพิ่มตัวแปรสำหรับตัวจับเวลา
private lateinit var dessertTimer : DessertTimer;
  1. เลื่อนลงไปที่ onCreate() แล้วสร้างออบเจ็กต์ DessertTimer ใหม่ต่อจากคำสั่งเรียกใช้ setOnClickListener()
dessertTimer = DessertTimer()


ตอนนี้คุณมีออบเจ็กต์ตัวจับเวลาของหวานแล้ว ให้พิจารณาว่าคุณควรเริ่มและหยุดตัวจับเวลาที่ใดเพื่อให้ตัวจับเวลาทำงานเฉพาะเมื่อกิจกรรมอยู่บนหน้าจอ คุณจะเห็นตัวเลือกบางอย่างในขั้นตอนถัดไป

ขั้นตอนที่ 2: เริ่มและหยุดตัวจับเวลา

ระบบจะเรียกใช้เมธอด onStart() ก่อนที่กิจกรรมจะปรากฏ ระบบจะเรียกใช้เมธอด onStop() หลังจากที่กิจกรรมหยุดแสดง ดูเหมือนว่าการเรียกกลับเหล่านี้จะเป็นตัวเลือกที่ดีในการกำหนดเวลาเริ่มต้นและหยุดตัวจับเวลา

  1. ในMainActivity คลาส ให้เริ่มตัวจับเวลาในonStart() การเรียกกลับ
override fun onStart() {
   super.onStart()
   dessertTimer.startTimer()

   Timber.i("onStart called")
}
  1. หยุดตัวจับเวลาใน onStop():
override fun onStop() {
   super.onStop()
   dessertTimer.stopTimer()

   Timber.i("onStop Called")
}
  1. คอมไพล์และเรียกใช้แอป ใน Android Studio ให้คลิกแผง Logcat ในช่องค้นหา Logcat ให้ป้อน dessertclicker ซึ่งจะกรองตามทั้งคลาส MainActivity และ DessertTimer โปรดทราบว่าเมื่อแอปเริ่มทำงาน ตัวจับเวลาก็จะเริ่มทำงานทันทีเช่นกัน
  2. คลิกปุ่มกลับ แล้วสังเกตว่าตัวจับเวลาหยุดอีกครั้ง ตัวจับเวลาจะหยุดเนื่องจากทั้งกิจกรรมและตัวจับเวลาที่ควบคุมกิจกรรมถูกทำลายไปแล้ว
  3. ใช้หน้าจอล่าสุดเพื่อกลับไปที่แอป สังเกตใน Logcat ว่าตัวจับเวลาจะรีสตาร์ทจาก 0
  4. คลิกปุ่มแชร์ สังเกตใน Logcat ว่าตัวจับเวลายังคงทำงานอยู่

  5. คลิกปุ่มหน้าแรก สังเกตใน Logcat ว่าตัวจับเวลาหยุดทำงาน
  6. ใช้หน้าจอแอปที่ใช้ล่าสุดเพื่อกลับไปที่แอป สังเกตใน Logcat ว่าตัวจับเวลาจะเริ่มอีกครั้งจากจุดที่หยุดไว้
  7. ใน MainActivity ในเมธอด onStop() ให้ใส่ความคิดเห็นในการเรียกใช้ stopTimer() การแสดงความคิดเห็นใน stopTimer() แสดงให้เห็นกรณีที่คุณเริ่มการดำเนินการใน onStart() แต่ลืมหยุดการดำเนินการอีกครั้งใน onStop()
  8. คอมไพล์และเรียกใช้แอป แล้วคลิกปุ่มหน้าแรกหลังจากที่ตัวจับเวลาเริ่มทำงาน แม้ว่าแอปจะทำงานในเบื้องหลัง แต่ตัวจับเวลาจะยังคงทำงานและใช้ทรัพยากรของระบบอย่างต่อเนื่อง การปล่อยให้ตัวจับเวลาทำงานต่อไปจะทำให้แอปของคุณเกิดการรั่วไหลของหน่วยความจำ และอาจไม่ใช่ลักษณะการทำงานที่คุณต้องการ

    รูปแบบทั่วไปคือเมื่อคุณตั้งค่าหรือเริ่มดำเนินการบางอย่างในโค้ดเรียกกลับ คุณจะต้องหยุดหรือนำสิ่งนั้นออกในโค้ดเรียกกลับที่เกี่ยวข้อง วิธีนี้จะช่วยให้คุณหลีกเลี่ยงการเรียกใช้สิ่งที่ไม่จำเป็นอีกต่อไป
  1. ยกเลิกการแสดงความคิดเห็นในบรรทัดใน onStop() ที่คุณหยุดตัวจับเวลา
  2. ตัดและวางการเรียก startTimer() จาก onStart() ไปยัง onCreate() การเปลี่ยนแปลงนี้แสดงให้เห็นกรณีที่คุณทั้งเริ่มต้นและเริ่มทรัพยากรใน onCreate() แทนที่จะใช้ onCreate() เพื่อเริ่มต้นและ onStart() เพื่อเริ่ม
  3. คอมไพล์และเรียกใช้แอป คุณจะเห็นว่าตัวจับเวลาเริ่มทำงานตามที่คาดไว้
  4. คลิกหน้าแรกเพื่อหยุดแอป ตัวจับเวลาจะหยุดทำงานตามที่คาดไว้
  5. ใช้หน้าจอแอปที่ใช้ล่าสุดเพื่อกลับไปยังแอป โปรดทราบว่าในกรณีนี้ ตัวจับเวลาจะไม่เริ่มอีกครั้ง เนื่องจาก onCreate() จะเรียกใช้เมื่อแอปเริ่มต้นเท่านั้น ไม่ได้เรียกใช้เมื่อแอปกลับมาทำงานอยู่เบื้องหน้า

ข้อควรทราบ

  • เมื่อตั้งค่าทรัพยากรในการเรียกกลับของวงจร ให้ยกเลิกการจัดสรรทรัพยากรด้วย
  • ทำการตั้งค่าและล้างข้อมูลในเมธอดที่เกี่ยวข้อง
  • หากตั้งค่าบางอย่างใน onStart() ให้หยุดหรือยกเลิกการตั้งค่าใน onStop()

ในแอป DessertClicker คุณจะเห็นได้ง่ายๆ ว่าหากเริ่มตัวจับเวลาใน onStart() คุณก็ต้องหยุดตัวจับเวลาใน onStop() มีตัวจับเวลาเพียงตัวเดียว จึงจำได้ง่ายว่าต้องหยุดตัวจับเวลา

ในแอป Android ที่ซับซ้อนมากขึ้น คุณอาจตั้งค่าหลายอย่างใน onStart() หรือ onCreate() จากนั้นจึงล้างข้อมูลทั้งหมดใน onStop() หรือ onDestroy() เช่น คุณอาจมีภาพเคลื่อนไหว เพลง เซ็นเซอร์ หรือตัวจับเวลาที่ต้องทั้งตั้งค่าและปิด รวมถึงเริ่มและหยุด หากลืมไปข้อหนึ่ง ก็จะทำให้เกิดข้อบกพร่องและปวดหัว

ไลบรารีวงจรของแอปซึ่งเป็นส่วนหนึ่งของ Android Jetpack จะช่วยให้งานนี้ง่ายขึ้น ไลบรารีมีประโยชน์อย่างยิ่งในกรณีที่คุณต้องติดตามองค์ประกอบที่เปลี่ยนแปลงหลายอย่าง ซึ่งบางอย่างอยู่ในสถานะวงจรที่แตกต่างกัน ไลบรารีจะพลิกวิธีการทำงานของวงจร: โดยปกติแล้วกิจกรรมหรือ Fragment จะบอกคอมโพเนนต์ (เช่น DessertTimer) ว่าต้องทำอะไรเมื่อมีการเรียกกลับของวงจร แต่เมื่อใช้ไลบรารีวงจรของคอมโพเนนต์ คอมโพเนนต์จะคอยสังเกตการเปลี่ยนแปลงวงจรของคอมโพเนนต์เอง จากนั้นจะทำสิ่งที่จำเป็นเมื่อเกิดการเปลี่ยนแปลงเหล่านั้น

ไลบรารีวงจรลูกค้ามี 3 ส่วนหลักๆ ดังนี้

  • เจ้าของวงจร ซึ่งเป็นคอมโพเนนต์ที่มีวงจร (และจึง "เป็นเจ้าของ") Activity และ Fragment เป็นเจ้าของวงจร เจ้าของวงจรจะใช้LifecycleOwnerอินเทอร์เฟซ
  • Lifecycle คลาสที่เก็บสถานะจริงของเจ้าของวงจรและทริกเกอร์เหตุการณ์เมื่อมีการเปลี่ยนแปลงวงจร
  • Observer ของวงจร ซึ่งจะสังเกตสถานะวงจรและทำงานเมื่อวงจรเปลี่ยนแปลง ผู้สังเกตการณ์วงจรจะใช้LifecycleObserverอินเทอร์เฟซ

ในงานนี้ คุณจะแปลงแอป DessertClicker ให้ใช้ไลบรารีวงจรของ Android และเรียนรู้วิธีที่ไลบรารีช่วยให้การทำงานกับวงจรกิจกรรมและวงจร Fragment ของ Android จัดการได้ง่ายขึ้น

ขั้นตอนที่ 1: เปลี่ยน DessertTimer เป็น LifecycleObserver

ส่วนสำคัญของไลบรารีวงจรคือแนวคิดการสังเกตวงจร การสังเกตช่วยให้คลาส (เช่น DessertTimer) ทราบเกี่ยวกับวงจรของกิจกรรมหรือ Fragment รวมถึงเริ่มและหยุดตัวเองเพื่อตอบสนองต่อการเปลี่ยนแปลงสถานะวงจรเหล่านั้น LifecycleObserver ช่วยให้คุณไม่ต้องรับผิดชอบในการเริ่มและหยุดออบเจ็กต์จากเมธอดของกิจกรรมและ Fragment

  1. เปิดDesertTimer.ktชั้นเรียน
  2. เปลี่ยนลายเซ็นของคลาส DessertTimer ให้มีลักษณะดังนี้
class DessertTimer(lifecycle: Lifecycle) : LifecycleObserver {

คำจำกัดความของคลาสใหม่นี้จะทำ 2 สิ่งต่อไปนี้

  • ตัวสร้างจะรับออบเจ็กต์ Lifecycle ซึ่งเป็นวงจรที่ตัวจับเวลาสังเกต
  • คำจำกัดความของคลาสจะใช้ LifecycleObserver อินเทอร์เฟซ
  1. เพิ่มบล็อก init ลงในคำจำกัดความของคลาสใต้ตัวแปร runnable ในบล็อก init ให้ใช้วิธี addObserver() เพื่อเชื่อมต่อออบเจ็กต์วงจรที่ส่งมาจากเจ้าของ (กิจกรรม) กับคลาสนี้ (Observer)
 init {
   lifecycle.addObserver(this)
}
  1. ใส่คำอธิบายประกอบ startTimer() ด้วย @OnLifecycleEvent annotation และใช้เหตุการณ์วงจรลูกค้า ON_START เหตุการณ์วงจรทั้งหมดที่เครื่องสังเกตวงจรสังเกตได้จะอยู่ในคลาส Lifecycle.Event
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun startTimer() {
  1. ทำเช่นเดียวกันกับ stopTimer() โดยใช้เหตุการณ์ ON_STOP ดังนี้
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stopTimer()

ขั้นตอนที่ 2: แก้ไข MainActivity

คลาส MainActivity ของคุณเป็นเจ้าของวงจรอยู่แล้วผ่านการรับค่า เนื่องจากคลาสซูเปอร์ FragmentActivity ใช้ LifecycleOwner ดังนั้น คุณจึงไม่ต้องดำเนินการใดๆ เพื่อให้กิจกรรมของคุณรับรู้ถึงวงจรของกิจกรรม สิ่งที่คุณต้องทำคือส่งออบเจ็กต์วงจรของกิจกรรมไปยังเครื่องมือสร้าง DessertTimer

  1. เปิด MainActivity ในonCreate() ให้แก้ไขการเริ่มต้นของ DessertTimer เพื่อรวม this.lifecycle ดังนี้
dessertTimer = DessertTimer(this.lifecycle)

พร็อพเพอร์ตี้ lifecycle ของกิจกรรมมีออบเจ็กต์ Lifecycle ที่กิจกรรมนี้เป็นเจ้าของ

  1. นำการโทรไปยัง startTimer() ใน onCreate() และการโทรไปยัง stopTimer() ใน onStop() ออก คุณไม่จำเป็นต้องบอก DessertTimer ว่าต้องทำอะไรในกิจกรรมอีกต่อไป เนื่องจากตอนนี้ DessertTimer จะสังเกตวงจรด้วยตัวเองและจะได้รับการแจ้งเตือนโดยอัตโนมัติเมื่อสถานะวงจรเปลี่ยนไป ตอนนี้สิ่งที่คุณทำในฟังก์ชันเรียกกลับเหล่านี้คือการบันทึกข้อความ
  2. คอมไพล์และเรียกใช้แอป แล้วเปิด Logcat คุณจะเห็นว่าตัวจับเวลาเริ่มทำงานตามที่คาดไว้
  3. คลิกปุ่มหน้าแรกเพื่อย้ายแอปไปไว้ที่พื้นหลัง สังเกตว่าตัวจับเวลาหยุดทำงานตามที่คาดไว้

จะเกิดอะไรขึ้นกับแอปและข้อมูลของแอปหาก Android ปิดแอปขณะที่แอปทำงานในเบื้องหลัง คุณควรทำความเข้าใจกรณีข้อยกเว้นที่ซับซ้อนนี้

เมื่อแอปเข้าสู่เบื้องหลัง ระบบจะไม่ทำลายแอป แต่จะหยุดแอปและรอให้ผู้ใช้กลับมาที่แอป แต่ข้อกังวลหลักอย่างหนึ่งของระบบปฏิบัติการ Android คือการทำให้กิจกรรมที่อยู่เบื้องหน้าทำงานได้อย่างราบรื่น ตัวอย่างเช่น หากผู้ใช้ใช้แอป GPS เพื่อช่วยให้ทันรถประจำทาง คุณก็ควรแสดงแอป GPS นั้นอย่างรวดเร็วและแสดงเส้นทางต่อไป การทำให้แอป DessertClicker ซึ่งผู้ใช้อาจไม่ได้ดูมา 2-3 วันทำงานได้อย่างราบรื่นในเบื้องหลังจึงมีความสำคัญน้อยกว่า

Android ควบคุมแอปในเบื้องหลังเพื่อให้แอปในเบื้องหน้าทำงานได้โดยไม่มีปัญหา เช่น Android จะจำกัดปริมาณการประมวลผลที่แอปซึ่งทำงานในเบื้องหลังสามารถทำได้

บางครั้ง Android จะปิดกระบวนการของแอปทั้งหมด ซึ่งรวมถึงทุกกิจกรรมที่เชื่อมโยงกับแอป Android จะปิดในลักษณะนี้เมื่อระบบทำงานหนักและเสี่ยงต่อการหน่วงเวลาที่มองเห็นได้ ดังนั้นจึงไม่มีการเรียกกลับหรือโค้ดเพิ่มเติมที่ทำงานในตอนนี้ ระบบจะปิดกระบวนการของแอปอย่างเงียบๆ ในเบื้องหลัง แต่สำหรับผู้ใช้แล้ว จะดูเหมือนว่าแอปยังไม่ได้ปิด เมื่อผู้ใช้กลับไปที่แอปที่ระบบปฏิบัติการ Android ปิดไป Android จะรีสตาร์ทแอปนั้น

ในงานนี้ คุณจะจำลองการปิดกระบวนการ Android และตรวจสอบสิ่งที่เกิดขึ้นกับแอปเมื่อเริ่มทำงานอีกครั้ง

ขั้นตอนที่ 1: ใช้ adb เพื่อจำลองการปิดกระบวนการ

Android Debug Bridge (adb) เป็นเครื่องมือบรรทัดคำสั่งที่ช่วยให้คุณส่งคำสั่งไปยังโปรแกรมจำลองและอุปกรณ์ที่เชื่อมต่อกับคอมพิวเตอร์ได้ ในขั้นตอนนี้ คุณจะใช้ adb เพื่อปิดกระบวนการของแอปและดูว่าจะเกิดอะไรขึ้นเมื่อ Android ปิดแอป

  1. คอมไพล์และเรียกใช้แอป คลิกคัพเค้ก 2-3 ครั้ง
  2. กดปุ่มหน้าแรกเพื่อนำแอปไปไว้ที่พื้นหลัง ตอนนี้ระบบได้หยุดแอปแล้ว และแอปอาจถูกปิดหาก Android ต้องการทรัพยากรที่แอปใช้อยู่
  3. ใน Android Studio ให้คลิกแท็บเทอร์มินัลเพื่อเปิดเทอร์มินัลบรรทัดคำสั่ง
  4. พิมพ์ adb แล้วกด Return

    หากเห็นเอาต์พุตจำนวนมากที่ขึ้นต้นด้วย Android Debug Bridge version X.XX.X และลงท้ายด้วย tags to be used by logcat (see logcat —help) แสดงว่าทุกอย่างปกติดี หากเห็น adb: command not found แทน ให้ตรวจสอบว่าคำสั่ง adb พร้อมใช้งานในเส้นทางการดำเนินการ ดูวิธีการได้ที่ "เพิ่ม adb ลงในเส้นทางการดำเนินการ" ใน บทที่เกี่ยวกับยูทิลิตี
  5. คัดลอกความคิดเห็นนี้แล้ววางลงในบรรทัดคำสั่ง จากนั้นกด Return
adb shell am kill com.example.android.dessertclicker

คำสั่งนี้จะบอกให้อุปกรณ์หรือโปรแกรมจำลองที่เชื่อมต่ออยู่หยุดกระบวนการที่มีชื่อแพ็กเกจ dessertclicker แต่จะทำเช่นนี้ก็ต่อเมื่อแอปทำงานอยู่เบื้องหลังเท่านั้น เนื่องจากแอปของคุณทำงานในเบื้องหลัง จึงไม่มีสิ่งใดแสดงบนหน้าจออุปกรณ์หรือโปรแกรมจำลองเพื่อระบุว่าระบบหยุดกระบวนการแล้ว ใน Android Studio ให้คลิกแท็บเรียกใช้เพื่อดูข้อความที่ระบุว่า "แอปพลิเคชันสิ้นสุดแล้ว" คลิกแท็บ Logcat เพื่อดูว่าไม่มีการเรียกกลับ onDestroy() และกิจกรรมของคุณสิ้นสุดลง

  1. ใช้หน้าจอ "ล่าสุด" เพื่อกลับไปที่แอป แอปจะปรากฏในส่วน "ล่าสุด" ไม่ว่าจะถูกย้ายไปไว้เบื้องหลังหรือหยุดการทำงานไปแล้วก็ตาม เมื่อใช้หน้าจอล่าสุดเพื่อกลับไปยังแอป ระบบจะเริ่มกิจกรรมอีกครั้ง กิจกรรมจะผ่านการเรียกกลับทั้งชุดของวงจรการเริ่มต้น รวมถึง onCreate()
  2. โปรดทราบว่าเมื่อแอปรีสตาร์ท ระบบจะรีเซ็ต "คะแนน" (ทั้งจำนวนของหวานที่ขายได้และยอดเงินดอลลาร์ทั้งหมด) เป็นค่าเริ่มต้น (0) หาก Android ปิดแอปของคุณ ทำไมจึงไม่บันทึกสถานะ

    เมื่อระบบปฏิบัติการรีสตาร์ทแอปให้คุณ Android จะพยายามอย่างเต็มที่เพื่อรีเซ็ตแอปกลับไปเป็นสถานะก่อนหน้า Android จะนำสถานะของ View บางรายการของคุณไปบันทึกไว้ใน Bundle ทุกครั้งที่คุณออกจากกิจกรรม ตัวอย่างข้อมูลที่ระบบบันทึกโดยอัตโนมัติ ได้แก่ ข้อความใน EditText (ตราบใดที่มีการตั้งค่ารหัสในเลย์เอาต์) และสแต็กย้อนกลับของกิจกรรม

    อย่างไรก็ตาม บางครั้งระบบปฏิบัติการ Android อาจไม่ทราบข้อมูลทั้งหมดของคุณ ตัวอย่างเช่น หากคุณมีตัวแปรที่กำหนดเอง เช่น revenue ในแอป DessertClicker ระบบปฏิบัติการ Android จะไม่ทราบข้อมูลนี้หรือความสำคัญของข้อมูลต่อกิจกรรมของคุณ คุณต้องเพิ่มข้อมูลนี้ลงในแพ็กเกจด้วยตนเอง

ขั้นตอนที่ 2: ใช้ onSaveInstanceState() เพื่อบันทึกข้อมูล Bundle

เมธอด onSaveInstanceState() คือ Callback ที่คุณใช้เพื่อบันทึกข้อมูลที่อาจจำเป็นในกรณีที่ระบบปฏิบัติการ Android ทำลายแอปของคุณ ในแผนภาพ Callback ของวงจร onSaveInstanceState() จะได้รับการเรียกใช้หลังจากที่หยุดกิจกรรมแล้ว ระบบจะเรียกใช้ทุกครั้งที่แอปเข้าสู่เบื้องหลัง

ให้คิดว่าการเรียก onSaveInstanceState() เป็นมาตรการด้านความปลอดภัย ซึ่งจะช่วยให้คุณมีโอกาสบันทึกข้อมูลจำนวนเล็กน้อยลงใน Bundle เมื่อกิจกรรมออกจากเบื้องหน้า ระบบจะบันทึกข้อมูลนี้ในตอนนี้เนื่องจากหากรอจนกว่าจะปิดแอป ระบบปฏิบัติการอาจมีทรัพยากรไม่เพียงพอ การบันทึกข้อมูลทุกครั้งจะช่วยให้มั่นใจได้ว่าข้อมูลอัปเดตในแพ็กเกจพร้อมให้กู้คืนหากจำเป็น

  1. ใน MainActivity ให้ลบล้างการเรียกกลับ onSaveInstanceState() แล้วเพิ่มคำสั่งบันทึก Timber
override fun onSaveInstanceState(outState: Bundle) {
   super.onSaveInstanceState(outState)

   Timber.i("onSaveInstanceState Called")
}
  1. คอมไพล์และเรียกใช้แอป แล้วคลิกปุ่มหน้าแรกเพื่อนำแอปไปไว้เบื้องหลัง โปรดสังเกตว่าการเรียกกลับ onSaveInstanceState() จะเกิดขึ้นหลังจาก onPause() และ onStop():
  2. ที่ด้านบนของไฟล์ ก่อนคำจำกัดความของคลาส ให้เพิ่มค่าคงที่ต่อไปนี้
const val KEY_REVENUE = "revenue_key"
const val KEY_DESSERT_SOLD = "dessert_sold_key"
const val KEY_TIMER_SECONDS = "timer_seconds_key"

คุณจะใช้คีย์เหล่านี้ทั้งในการบันทึกและดึงข้อมูลจากแพ็กเกจสถานะอินสแตนซ์

  1. เลื่อนลงไปที่ onSaveInstanceState() แล้วสังเกตพารามิเตอร์ outState ซึ่งมีประเภทเป็น Bundle

    Bundle คือชุดของคู่คีย์-ค่า โดยคีย์จะเป็นสตริงเสมอ คุณใส่ค่าดั้งเดิม เช่น ค่า int และ boolean ลงใน Bundle ได้
    เนื่องจากระบบจะเก็บชุดข้อมูลนี้ไว้ใน RAM แนวทางปฏิบัติแนะนำคือการเก็บข้อมูลในชุดข้อมูลให้มีขนาดเล็ก นอกจากนี้ ขนาดของแพ็กเกจนี้ยังถูกจำกัดด้วย แต่ขนาดจะแตกต่างกันไปในแต่ละอุปกรณ์ โดยทั่วไปแล้ว คุณควรจัดเก็บข้อมูลน้อยกว่า 100, 000 รายการ มิฉะนั้นแอปอาจขัดข้องและแสดงข้อผิดพลาด TransactionTooLargeException
  2. ใน onSaveInstanceState() ให้ใส่ค่า revenue (จำนวนเต็ม) ลงในกลุ่มด้วยเมธอด putInt()
outState.putInt(KEY_REVENUE, revenue)

เมธอด putInt() (และเมธอดที่คล้ายกันจากคลาส Bundle เช่น putFloat() และ putString()) จะรับอาร์กิวเมนต์ 2 รายการ ได้แก่ สตริงสำหรับคีย์ (ค่าคงที่ KEY_REVENUE) และค่าจริงที่จะบันทึก

  1. ทำกระบวนการเดียวกันซ้ำกับจำนวนของหวานที่ขายและสถานะของตัวจับเวลา
outState.putInt(KEY_DESSERT_SOLD, dessertsSold)
outState.putInt(KEY_TIMER_SECONDS, dessertTimer.secondsCount)

ขั้นตอนที่ 3: ใช้ onCreate() เพื่อคืนค่าข้อมูล Bundle

  1. เลื่อนขึ้นไปที่ onCreate() แล้วตรวจสอบลายเซ็นของเมธอด
override fun onCreate(savedInstanceState: Bundle) {

โปรดสังเกตว่า onCreate() จะได้รับ Bundle ทุกครั้งที่มีการเรียกใช้ เมื่อกิจกรรมของคุณรีสตาร์ทเนื่องจากกระบวนการปิดตัวลง ระบบจะส่งต่อ Bundle ที่คุณบันทึกไว้ไปยัง onCreate() หากกิจกรรมของคุณเพิ่งเริ่มต้น แพ็กเกจนี้ใน onCreate() จะเป็น null ดังนั้นหากไม่มีการรวมกลุ่ม null คุณจะทราบว่าคุณกำลัง "สร้างใหม่" กิจกรรมจากจุดที่ทราบก่อนหน้านี้

  1. เพิ่มโค้ดนี้ลงใน onCreate() หลังจากตั้งค่า DessertTimer แล้ว:
if (savedInstanceState != null) {
   revenue = savedInstanceState.getInt(KEY_REVENUE, 0)
}

การทดสอบสำหรับ null จะพิจารณาว่ามีข้อมูลใน Bundle หรือไม่ หรือ Bundle เป็น null หรือไม่ ซึ่งจะบอกคุณว่าแอปเริ่มต้นใหม่หรือสร้างขึ้นใหม่หลังจากปิดเครื่อง การทดสอบนี้เป็นรูปแบบทั่วไปสำหรับการกู้คืนข้อมูลจากแพ็กเกจ

โปรดทราบว่าคีย์ที่คุณใช้ที่นี่ (KEY_REVENUE) เป็นคีย์เดียวกับที่คุณใช้สำหรับ putInt() แนวทางปฏิบัติแนะนำคือการกำหนดคีย์เหล่านั้นเป็นค่าคงที่เพื่อให้แน่ใจว่าคุณใช้คีย์เดียวกันทุกครั้ง คุณใช้ getInt() เพื่อนำข้อมูลออกจาก Bundle เช่นเดียวกับที่ใช้ putInt() เพื่อใส่ข้อมูลลงใน Bundle เมธอด getInt() รับอาร์กิวเมนต์ 2 รายการ ดังนี้

  • สตริงที่ทำหน้าที่เป็นคีย์ เช่น "key_revenue" สำหรับมูลค่ารายได้
  • ค่าเริ่มต้นในกรณีที่ไม่มีค่าสำหรับคีย์นั้นในชุด

จากนั้นระบบจะกำหนดจำนวนเต็มที่คุณได้รับจาก Bundle ให้กับตัวแปร revenue และ UI จะใช้ค่านั้น

  1. เพิ่มเมธอด getInt() เพื่อคืนค่าจำนวนของหวานที่ขายและค่าของตัวจับเวลา
if (savedInstanceState != null) {
   revenue = savedInstanceState.getInt(KEY_REVENUE, 0)dessertsSold = savedInstanceState.getInt(KEY_DESSERT_SOLD, 0)
   dessertTimer.secondsCount =
       savedInstanceState.getInt(KEY_TIMER_SECONDS, 0)
}
  1. คอมไพล์และเรียกใช้แอป กดคัพเค้กอย่างน้อย 5 ครั้งจนกว่าจะเปลี่ยนเป็นโดนัท คลิกหน้าแรกเพื่อย้ายแอปไปไว้ที่พื้นหลัง
  2. ในแท็บเทอร์มินัลของ Android Studio ให้เรียกใช้ adb เพื่อปิดกระบวนการของแอป
adb shell am kill com.example.android.dessertclicker
  1. ใช้หน้าจอแอปที่ใช้ล่าสุดเพื่อกลับไปที่แอป โปรดสังเกตว่าครั้งนี้แอปจะกลับมาพร้อมกับรายได้และมูลค่าของของหวานที่ขายได้จากแพ็กเกจที่ถูกต้อง แต่ก็สังเกตด้วยว่าของหวานกลับมาเป็นคัพเค้กแล้ว คุณต้องทำอีกอย่างเพื่อให้แน่ใจว่าแอปจะกลับมาทำงานต่อจากที่ปิดไปได้เหมือนเดิม
  2. ใน MainActivity ให้ตรวจสอบเมธอด showCurrentDessert() โปรดทราบว่าวิธีนี้จะกำหนดว่าควรแสดงรูปภาพของหวานใดในกิจกรรมโดยอิงตามจำนวนของหวานที่ขายได้ในปัจจุบันและรายการของหวานในตัวแปร allDesserts
for (dessert in allDesserts) {
   if (dessertsSold >= dessert.startProductionAmount) {
       newDessert = dessert
   }
    else break
}

วิธีนี้จะอิงตามจำนวนของหวานที่ขายได้เพื่อเลือกรูปภาพที่เหมาะสม ดังนั้น คุณจึงไม่จำเป็นต้องดำเนินการใดๆ เพื่อจัดเก็บการอ้างอิงถึงรูปภาพในชุดใน onSaveInstanceState() ในแพ็กเกจนั้น คุณจัดเก็บจำนวนของหวานที่ขายไปแล้ว

  1. ใน onCreate() ในบล็อกที่กู้คืนสถานะจาก Bundle ให้เรียกใช้ showCurrentDessert():
 if (savedInstanceState != null) {
   revenue = savedInstanceState.getInt(KEY_REVENUE, 0)
   dessertsSold = savedInstanceState.getInt(KEY_DESSERT_SOLD, 0)
   dessertTimer.secondsCount = 
      savedInstanceState.getInt(KEY_TIMER_SECONDS, 0)
   showCurrentDessert()                   
}
  1. คอมไพล์และเรียกใช้แอป แล้ววางไว้ในเบื้องหลัง ใช้ adb เพื่อปิดกระบวนการ ใช้หน้าจอแอปที่ใช้ล่าสุดเพื่อกลับไปที่แอป โปรดทราบว่าตอนนี้ระบบได้กู้คืนทั้งค่าของขนมหวานที่บอก รายได้รวม และรูปภาพขนมหวานอย่างถูกต้องแล้ว

ในส่วนของการจัดการวงจรของกิจกรรมและ Fragment ยังมีกรณีพิเศษอีก 1 กรณีที่คุณควรทำความเข้าใจ นั่นคือการเปลี่ยนแปลงการกำหนดค่าส่งผลต่อวงจรของกิจกรรมและ Fragment อย่างไร

การเปลี่ยนแปลงการกำหนดค่าจะเกิดขึ้นเมื่อสถานะของอุปกรณ์เปลี่ยนแปลงอย่างมากจนวิธีที่ง่ายที่สุดสำหรับระบบในการแก้ไขการเปลี่ยนแปลงคือการปิดเครื่องโดยสมบูรณ์และสร้างกิจกรรมใหม่ ตัวอย่างเช่น หากผู้ใช้เปลี่ยนภาษาของอุปกรณ์ อาจต้องเปลี่ยนเลย์เอาต์ทั้งหมดเพื่อให้รองรับทิศทางของข้อความที่แตกต่างกัน หากผู้ใช้เสียบอุปกรณ์เข้ากับแท่นวางหรือเพิ่มแป้นพิมพ์จริง เลย์เอาต์ของแอปอาจต้องใช้ประโยชน์จากขนาดหรือเลย์เอาต์การแสดงผลที่แตกต่างกัน และหากการวางแนวอุปกรณ์เปลี่ยนไป เช่น หากหมุนอุปกรณ์จากแนวตั้งเป็นแนวนอนหรือหมุนกลับ เลย์เอาต์อาจต้องเปลี่ยนเพื่อให้พอดีกับการวางแนวใหม่

ขั้นตอนที่ 1: สำรวจการหมุนเวียนอุปกรณ์และการเรียกกลับวงจรของอุปกรณ์

  1. คอมไพล์และเรียกใช้แอป แล้วเปิด Logcat
  2. หมุนอุปกรณ์หรือโปรแกรมจำลองเป็นโหมดแนวนอน คุณหมุนโปรแกรมจำลองไปทางซ้ายหรือขวาได้ด้วยปุ่มหมุน หรือด้วยปุ่ม Control และปุ่มลูกศร (Command และปุ่มลูกศรใน Mac)
  3. ตรวจสอบเอาต์พุตใน Logcat กรองเอาต์พุตใน MainActivity
    โปรดทราบว่าเมื่ออุปกรณ์หรือโปรแกรมจำลองหมุนหน้าจอ ระบบจะเรียกใช้การเรียกกลับของวงจรทั้งหมดเพื่อปิดกิจกรรม จากนั้นเมื่อมีการสร้างกิจกรรมขึ้นใหม่ ระบบจะเรียกใช้การเรียกกลับของวงจรทั้งหมดเพื่อเริ่มกิจกรรม
  4. ใน MainActivity ให้ใส่ความคิดเห็นในเมธอด onSaveInstanceState() ทั้งหมด
  5. คอมไพล์และเรียกใช้แอปอีกครั้ง คลิกคัพเค้ก 2-3 ครั้ง แล้วหมุนอุปกรณ์หรือโปรแกรมจำลอง คราวนี้เมื่อหมุนอุปกรณ์และปิดกิจกรรมแล้วสร้างใหม่ กิจกรรมจะเริ่มต้นด้วยค่าเริ่มต้น

    เมื่อมีการเปลี่ยนแปลงการกำหนดค่า Android จะใช้ชุดสถานะอินสแตนซ์เดียวกันกับที่คุณได้เรียนรู้ในงานก่อนหน้าเพื่อบันทึกและกู้คืนสถานะของแอป เช่นเดียวกับการปิดกระบวนการ ให้ใช้ onSaveInstanceState() เพื่อใส่ข้อมูลของแอปไว้ในชุด จากนั้นกู้คืนข้อมูลใน onCreate() เพื่อหลีกเลี่ยงการสูญเสียข้อมูลสถานะกิจกรรมหากหมุนอุปกรณ์
  6. ใน MainActivity ให้ยกเลิกการแสดงความคิดเห็นของเมธอด onSaveInstanceState() เรียกใช้แอป คลิกคัพเค้ก แล้วหมุนแอปหรืออุปกรณ์ โปรดสังเกตว่าคราวนี้ระบบจะเก็บข้อมูลของหวานไว้ตลอดการหมุนเวียนกิจกรรม

โปรเจ็กต์ Android Studio: DessertClickerFinal

เคล็ดลับเกี่ยวกับวงจร

  • หากตั้งค่าหรือเริ่มการทำงานในโค้ดเรียกกลับของวงจรการใช้งาน ให้หยุดหรือนำสิ่งนั้นออกในโค้ดเรียกกลับที่เกี่ยวข้อง การหยุดสิ่งต่างๆ จะช่วยให้มั่นใจได้ว่าสิ่งนั้นจะไม่ทำงานต่อไปเมื่อไม่จำเป็นต้องใช้อีกต่อไป เช่น หากตั้งตัวจับเวลาใน onStart() คุณจะต้องหยุดชั่วคราวหรือหยุดตัวจับเวลาใน onStop()
  • ใช้ onCreate() เฉพาะเพื่อเริ่มต้นส่วนต่างๆ ของแอปที่ทำงานครั้งเดียวเมื่อแอปเริ่มทำงานเป็นครั้งแรก ใช้ onStart() เพื่อเริ่มต้นส่วนต่างๆ ของแอปที่ทำงานทั้งเมื่อแอปเริ่มต้นและทุกครั้งที่แอปกลับมาที่เบื้องหน้า

คลังวงจรลูกค้า

  • ใช้ไลบรารีวงจรของ Android เพื่อเปลี่ยนการควบคุมวงจรจากกิจกรรมหรือ Fragment ไปยังคอมโพเนนต์จริงที่ต้องรับรู้ถึงวงจร
  • เจ้าของวงจรเป็นคอมโพเนนต์ที่มีวงจร (และจึง "เป็นเจ้าของ") ซึ่งรวมถึง Activity และ Fragment เจ้าของวงจรจะใช้LifecycleOwnerอินเทอร์เฟซ
  • Observer ของวงจรจะสังเกตสถานะวงจรปัจจุบันและทำงานเมื่อวงจรเปลี่ยน ผู้สังเกตการณ์วงจรจะใช้LifecycleObserverอินเทอร์เฟซ
  • Lifecycle มีสถานะอายุการใช้งานจริง และจะทริกเกอร์เหตุการณ์เมื่ออายุการใช้งานเปลี่ยนแปลง

วิธีสร้างคลาสที่รับรู้ถึงวงจร

  • ใช้LifecycleObserverอินเทอร์เฟซในคลาสที่ต้องรับรู้ถึงวงจร
  • เริ่มต้นคลาสสังเกตการณ์วงจรด้วยออบเจ็กต์วงจรจากกิจกรรมหรือ Fragment
  • ในคลาส LifecycleObserver ให้ใส่คำอธิบายประกอบเมธอดที่รับรู้ถึงวงจรด้วยการเปลี่ยนแปลงสถานะวงจรที่เมธอดสนใจ

    เช่น คำอธิบายประกอบ @OnLifecycleEvent(Lifecycle.Event.ON_START) จะระบุว่าเมธอดกำลังดูเหตุการณ์วงจร onStart

การปิดกระบวนการและบันทึกสถานะกิจกรรม

  • Android ควบคุมแอปที่ทำงานในเบื้องหลังเพื่อให้แอปที่ทำงานในเบื้องหน้าทำงานได้โดยไม่มีปัญหา กฎระเบียบนี้รวมถึงการจำกัดปริมาณการประมวลผลที่แอปสามารถทำได้ในเบื้องหลัง และบางครั้งอาจถึงขั้นปิดกระบวนการของแอปทั้งหมด
  • ผู้ใช้จะไม่ทราบว่าระบบปิดแอปในเบื้องหลังหรือไม่ แอปจะยังคงปรากฏในหน้าจอแอปที่ใช้ล่าสุดและควรจะรีสตาร์ทในสถานะเดียวกับที่ผู้ใช้ปิดแอปไป
  • Android Debug Bridge (adb) เป็นเครื่องมือบรรทัดคำสั่งที่ช่วยให้คุณส่งคำสั่งไปยังโปรแกรมจำลองและอุปกรณ์ที่เชื่อมต่อกับคอมพิวเตอร์ได้ คุณใช้ adb เพื่อจำลองการปิดกระบวนการในแอปได้
  • เมื่อ Android ปิดกระบวนการของแอป ระบบจะไม่เรียกใช้เมธอดวงจรของ onDestroy() แอปหยุดทำงาน

การรักษาสถานะของกิจกรรมและ Fragment

  • เมื่อแอปเข้าสู่เบื้องหลัง ระบบจะบันทึกข้อมูลแอปเป็น Bundle ทันทีหลังจากเรียกใช้ onStop() ระบบจะบันทึกข้อมูลแอปบางอย่าง เช่น เนื้อหาของ EditText โดยอัตโนมัติ
  • Bundle คืออินสแตนซ์ของ Bundle ซึ่งเป็นคอลเล็กชันของคีย์และค่า คีย์จะเป็นสตริงเสมอ
  • ใช้onSaveInstanceState()การเรียกกลับเพื่อบันทึกข้อมูลอื่นๆ ลงใน Bundle ที่คุณต้องการเก็บไว้ แม้ว่าระบบจะปิดแอปโดยอัตโนมัติก็ตาม หากต้องการใส่ข้อมูลลงใน Bundle ให้ใช้วิธีการของ Bundle ที่ขึ้นต้นด้วย put เช่น putInt()
  • คุณสามารถนำข้อมูลออกจากแพ็กเกจได้ในonRestoreInstanceState()หรือonCreate() เมธอด onCreate() มีพารามิเตอร์ savedInstanceState ที่เก็บกลุ่ม
  • หากตัวแปร savedInstanceState มี null แสดงว่ากิจกรรมเริ่มต้นโดยไม่มีชุดสถานะและไม่มีข้อมูลสถานะที่จะดึงข้อมูล
  • หากต้องการดึงข้อมูลจาก Bundle ด้วยคีย์ ให้ใช้เมธอด Bundle ที่ขึ้นต้นด้วย get เช่น getInt()

การเปลี่ยนแปลงการกำหนดค่า

  • การเปลี่ยนแปลงการกำหนดค่าจะเกิดขึ้นเมื่อสถานะของอุปกรณ์เปลี่ยนแปลงอย่างมากจนวิธีที่ง่ายที่สุดสำหรับระบบในการแก้ไขการเปลี่ยนแปลงคือการปิดและสร้างกิจกรรมใหม่
  • ตัวอย่างที่พบบ่อยที่สุดของการเปลี่ยนแปลงการกำหนดค่าคือเมื่อผู้ใช้หมุนอุปกรณ์จากโหมดแนวตั้งเป็นแนวนอน หรือจากโหมดแนวนอนเป็นแนวตั้ง นอกจากนี้ การเปลี่ยนแปลงการกำหนดค่าอาจเกิดขึ้นเมื่อมีการเปลี่ยนภาษาของอุปกรณ์หรือเสียบแป้นพิมพ์ฮาร์ดแวร์
  • เมื่อมีการเปลี่ยนแปลงการกำหนดค่า Android จะเรียกใช้การเรียกกลับการปิดระบบของวงจรการทำงานของกิจกรรมทั้งหมด จากนั้น Android จะรีสตาร์ทกิจกรรมตั้งแต่ต้น โดยเรียกใช้การเรียกกลับการเริ่มต้นวงจรทั้งหมด
  • เมื่อ Android ปิดแอปเนื่องจากการเปลี่ยนแปลงการกำหนดค่า ระบบจะรีสตาร์ทกิจกรรมด้วยชุดสถานะที่พร้อมใช้งานสำหรับ onCreate()
  • เช่นเดียวกับการปิดกระบวนการ ให้บันทึกสถานะของแอปไปยัง Bundle ใน onSaveInstanceState()

หลักสูตร Udacity:

เอกสารประกอบสำหรับนักพัฒนาแอป Android

อื่นๆ:

ส่วนนี้แสดงรายการการบ้านที่เป็นไปได้สำหรับนักเรียน/นักศึกษาที่กำลังทำ Codelab นี้เป็นส่วนหนึ่งของหลักสูตรที่สอนโดยผู้สอน ผู้สอนมีหน้าที่ดำเนินการต่อไปนี้

  • มอบหมายการบ้านหากจำเป็น
  • สื่อสารกับนักเรียนเกี่ยวกับวิธีส่งงานที่ได้รับมอบหมาย
  • ให้คะแนนงานการบ้าน

ผู้สอนสามารถใช้คำแนะนำเหล่านี้ได้มากน้อยตามที่ต้องการ และควรมีอิสระในการมอบหมายการบ้านอื่นๆ ที่เห็นว่าเหมาะสม

หากคุณกำลังทำ Codelab นี้ด้วยตนเอง โปรดใช้แบบฝึกหัดเหล่านี้เพื่อทดสอบความรู้ของคุณ

เปลี่ยนแอป

เปิดแอป DiceRoller จากบทเรียนที่ 1 (คุณดาวน์โหลดแอปได้ที่นี่หากยังไม่มี) คอมไพล์และเรียกใช้แอป แล้วสังเกตว่าหากหมุนอุปกรณ์ ค่าปัจจุบันของลูกเต๋าจะหายไป ใช้ onSaveInstanceState() เพื่อคงค่าดังกล่าวไว้ในแพ็กเกจ และกู้คืนค่าดังกล่าวใน onCreate()

ตอบคำถามต่อไปนี้

คำถามที่ 1

แอปของคุณมีการจำลองฟิสิกส์ที่ต้องใช้การคำนวณอย่างหนักเพื่อแสดง จากนั้นผู้ใช้จะได้รับสายโทรศัพท์ คุณคิดว่าข้อใดต่อเป็นนี้เป็นจริง

  • ในระหว่างการโทร คุณควรคำนวณตำแหน่งของออบเจ็กต์ในการจำลองฟิสิกส์ต่อไป
  • ในระหว่างการโทร คุณควรหยุดการคำนวณตำแหน่งของออบเจ็กต์ในการจำลองฟิสิกส์

คำถามที่ 2

คุณควรแทนที่เมธอดวงจรใดเพื่อหยุดการจำลองชั่วคราวเมื่อแอปไม่อยู่บนหน้าจอ

  • onDestroy()
  • onStop()
  • onPause()
  • onSaveInstanceState()

คำถามที่ 3

หากต้องการทำให้คลาสรับรู้ถึงวงจรของคลาสผ่านไลบรารีวงจรของ Android คลาสควรใช้ฟีเจอร์ใด

  • Lifecycle
  • LifecycleOwner
  • Lifecycle.Event
  • LifecycleObserver

คำถามที่ 4

ในกรณีใดบ้างที่เมธอด onCreate() ในกิจกรรมของคุณได้รับ Bundle ที่มีข้อมูล (กล่าวคือ Bundle ไม่ใช่ null) อาจมีคำตอบมากกว่า 1 ข้อ

  • ระบบจะรีสตาร์ทกิจกรรมหลังจากหมุนอุปกรณ์
  • กิจกรรมเริ่มต้นจากศูนย์
  • ระบบจะกลับมาทำกิจกรรมต่อหลังจากกลับมาจากเบื้องหลัง
  • รีบูตอุปกรณ์แล้ว

เริ่มบทเรียนถัดไป: 5.1: ViewModel และ ViewModelFactory

ดูลิงก์ไปยัง Codelab อื่นๆ ในหลักสูตรนี้ได้ที่หน้า Landing Page ของ Codelab หลักพื้นฐานของ Android Kotlin