การสร้าง activity ขึ้นมาใหม่อีกครั้ง ใน activity lifecycle

เขียนเมื่อ 9 ปีก่อน โดย Ninenik Narkdee
android android studio activity lifecycle

คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ android android studio activity lifecycle

ดูแล้ว 4,534 ครั้ง


โดยปกติ app จะมีการกระทำไม่มากนัก ที่เป็นเหตุทำให้ activity ถูกทำลาย อย่างเช่น เมื่อผู้ใช้
กดที่ปุ่ม Back หรือ activity เรียกส่งคำสั่งให้ทำการทำลายตัวเองลงด้วยการเรียกใช้ finish()
หรือระบบยังอาจที่จะทำลาย activity ได้ ถ้ามันหยุดทำงานทันทีและไม่ถูกเรียกกลับมาใช้งาน
เป็นเวลานาน หรือ activity ที่ทำงานอยู่จะเป็นต้องใช้ทรัพยากรของระบบในปริมาณมากทำให้
ระบบต้องทำการปิดการทำงานที่อยู่เบื้องหลังเพื่อกู้คืนหน่วยความจำ
 
 
เมื่อ activity ถูกทำลายกรณีผู้ใช้กดปุ่ม Back หรือ activity จบการทำงานด้วยตัวมันเอง
โดยกรอบของระบบแล้ว acitivity instance จะถูกลบออกไปโดยสิ้นเชิง ด้วยเหตุผลที่ว่ามีการ
กระทำบ่งบอกได้ว่า activity ไม่จำเป็นต้องใช้งานแล้ว    อย่างไรก็ตาม ถ้าระบบทำลาย activity
ด้วยเหตุผลในเรื่องปัจจัยของระบบเป็นข้อจำกัด (กรณีมีมากกว่าการกระทำโดยทั่วไป) ถึงแม้ว่า
activity instance จะไม่มีแล้วก็ตาม ระบบยังคงจำว่ามันยังคงมีอยู่ อย่างเช่นถ้าเมื่อผู้ใช้กลับ
เข้ามาใช้งานอีก ระบบก็จะสร้าง instance ใหม่ของ activity ขึ้นมา ด้วยวิธีการใช้ข้อมูลที่ถูกบันทึก
ที่ระบุเกี่ยวกับ state ของ activity เมื่อตอนที่มันถูกทำลาย    ข้อมูลที่ถูกบันทึกที่ระบบใช้ในการ
กู้คืน state ก่อนหน้า เรียกว่า instance state  ซึ่งอยู่ในรุปแบบข้อมูลที่มี key กับ value เก็บค่าคู่กัน
ไว้ใน Bundle object
 
 
ข้อควรระวัง:: activity จถถูกทำลายและสร้างขึ้นมาใหม่ทุกๆ ครั้งที่ผู้ใช้หมุนหน้าจอ เมื่อใดก็ตาม
ที่หน้าจอมีการเปลี่ยนทิศทางการหมุน ระบบจะทำลายและสร้าง activity ที่ทำงานขึ้นมาใหม่
เพราะว่าการจัดโครงสร้างของหน้าจอ มีการเปลี่ยนแปลงและ activity อาจจำเป็นต้องโหลดหรือ
เรียกใช้งานทางเลือกการแสดง เช่น การเรียกใช้ layout แนวนอนหรือแนวตั้ง เป็นต้น
 
 
โดยค่าเริ่มต้น ระบบจะใช้งาน Bundle instance state เพื่อบันทึกข้อมูลเกี่ยวกับแต่ละ
view object ต่างๆ ใน activity layout (เช่น ค่าของข้อมูลที่กรอกใน EditText) ดังนั้น ถ้า 
activity instance ถูกทำลายและสร้างขึ้นมาใหม่ state ของ layout จะกลับคืนมาอยู่ใน state
เดิมก่อนหน้า โดยไม่จำเป็นต้องกำหนด code ใดๆ     อย่างไรก็ตาม activity อาจจะมี ข้อมูล
ของ state จำนวนมากที่จำเป็นต้องเรียกกลับมาใช้ เช่น ตัวแปรต่างๆ ที่ติดตามกระบวนการ
ทำงานที่กำลังดำเนินการของ activity
 
หมายเหตุ:: เพื่อให้ระบบของ android ทำการกู้คืน state ของ view object ใน activity แต่ละ
                view จำเป็นต้องกำหนด ID โดยใช้ android:id attribute
 
สำหรับการบันทึกข้อมูลเพิ่มเติมเกี่ยวกับ activity state   เราต้องเรียกใช้งาน  onSaveInstanceState() 
callback method    โดยระบบจะเรียกใช้งาน method นี้เมื่อผู้ใช้กำลังจะออกไปจาก activity และ 
Bundle object ก็จะถูกบันทึก หาก activity ถูกทำลายลงแบบไม่คาดคิด 
และถ้าระบบต้องการสร้าง activity instance ขึ้นมาใหม่ภายหลัง ระบบก็จะส่งค่า Bundle object เดิมไป
ทำการบันทึกทั้งในกรณี  onRestoreInstanceState() และ onCreate() method ถูกเรียกใช้งาน
 
 

 
 
จากรูป ขณะที่ระบบกำลังจะหยุดและทำลาย activity  มันจะเรียกใช้งาน onSaveInstanceState() (หมายเลข 1)
ดังนั้นเราสามารถกำหนดข้อมูล state เพิ่มเติมที่ต้องการบันทึกไว้ใช้งานเมื่อ activity instance ถูกสร้างขึ้นมาใหม่
ถ้าเมื่อ activity ถูกทำลายและมีการสร้าง instance ขึ้นมาใหม่ ระบบก็จะไปดึงข้อมูลที่ถูกบันทึกไว้ในขั้นตอน
หมายเลข 1 มาใช้งานเมื่อ method onCreate() (หมายเลข 2) และ onRestoreInstanceState() (หมายเลข 3)
ถูกเรียกใช้งาน
 


 
การบันทึก activity state
 
เมื่อ activity กำลังจะหยุดและถูกทำลาย ระบบจะเรียก method onSaveInstanceState() ดังนั้นใน method นี้
เราสามารถที่จะบันทึกข้อมูลเกี่ยวกับ state เก็บเป็นชุดข้อมูลที่มีค่า key และ value หรือที่เรียกว่า Bundle object
ค่าเริ่มต้นเกี่ยวกับการบันทึกข้อมูล state นั้น จะกำหนดตามลำดับขั้นของ view เช่น ข้อความที่กรอกไว้ใน  
EditText หรือ ตำแหน่งที่เลื่อนของ ListView
 
เพื่อทำการบันทึกข้อมูลเพิ่มเติม เกี่ยวกับ state เราต้องกำหนดค่าใน onSaveInstanceState() method และ
จัดเก็บข้อมูลในรูปแบบ key และ value เป็น Bundle object ดังตัวอย่างดังนี้
 
 
static final String STATE_SCORE = "playerScore";  // key STATE_SCORE ไว้เก็ยค่า คะแนนผู้เล่น
static final String STATE_LEVEL = "playerLevel";  // key STATE_LEVEL ไว้เก็บค่า level ผู้เล่น
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // บันทึกข้อมูลของผู้เล่นเกมส์ ปัจจุบัน ก่อน activity จะหยุดและถูกทำลายลง

    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
    
    //  เรียกใช้งาน superclass ก่อนทุกครั้งเสมอ เพื่อที่สามารถบันทึกข้อมูลตามลำดับขั้นได้
    super.onSaveInstanceState(savedInstanceState);
}
 
 
ข้อควรระวัง:: ต้องเรียกใช้งาน superclass กับ onSaveInstanceState()  method เพื่อที่เป็นการ
กำหนดค่าเริ่มต้นให้สามารถทำการบันทึกข้อมูลของ state ตามลำดับขั้นของ view ได้
 

 
การกู้คืนข้อมูล activity state
 
เมื่อ activity ถูกสร้างขึ้นมาใหม่ หลังจากได้ถูกทำลายลงไปก่อนหน้าแล้ว  เราสามารถกู้คืนข้อมูลของ state 
จาก Bundle object ที่ระบบได้ส่งค่าเก็บบันทึกไว้ได้   โดยการเรียกใช้งาน method ทั้ง onCreate() และ  
onRestoreInstanceState()  จะได้รับ Bundle object เดิมที่เก็บข้อมูลของ state ไว้
 
ด้วยการเรียกใช้งาน onCreate() method  ไม่ว่าระบบจะกำลังสร้าง instance ของ activity ใหม่ หรือ สร้าง
จาก instance เดิมขึ้นมาใหม่  เราต้องทำการตรวจสอบว่า Bundle เป็นค่า null หรือค่าว่างหรือไม่ เสมอ ก่อน
ที่เราจะพยายามอ่านค่าของมัน ถ้าค่า Bundle เป็นค่าว่าง แล้วระบบกำจะสร้าง instance ใหม่ของ activity 
แทนการกู้คืนจากค่าก่อนที่ถูกทำลาย
 
 
ยกตัวอย่าง ที่แสดงให้เห็นว่าเราสามารถกู้คืนบางค่าของข้อมูลใน onCreate() method
 
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // เรียกใช้งาน superclass ก่อนทุกครั้งเสมอ
   
    // ตรวจสอบว่า เรามีการสร้างมีการบันทึกของ instance ก่อนหน้าหรือไม่
    if (savedInstanceState != null) { // ถ้าค่าไม่ว่าง หรือก็คือมีการบันทึก instance
        // กู้คืนค่าข้อมูลจาก instance state ที่ถูกบันทึกไว้
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else { // กรณีสร้างใหม่
        // กำหนดค่าเริ่มต้นให้กับ instance กรณ๊สร้างใหม่
    }
    ...
}
 
 
แทนที่เราจะเรียกคืนค่าของ state ในขณะที่เรียกใช้งาน onCreate() method  เราอาจจะใช้ 
onRestoreInstanceState() method แทนได้  โดยระบบเรียกใช้งานต่อจาก onStart() method
ระบบเรียกใช้งาน onRestoreInstanceState() ในกรณีเมื่อมีข้อมูลถูกบันทึกสำหรับกู้คืนเท่านั้น
ดังนั้นเราไม่จำเป็นต้องตรวจสอบว่า Bundle เป้นค่าว่างหรือไม่
 
public void onRestoreInstanceState(Bundle savedInstanceState) {
    // เรียกใช้งาน superclass ก่อนทุกครั้งเสมอ เพื่อที่สามารถบันทึกข้อมูลตามลำดับขั้นได้
    super.onRestoreInstanceState(savedInstanceState);
   
    // กู้คืนค่าข้อมูลจาก instance state ที่ถูกบันทึกไว้
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
 
 
 
ข้อควรระวัง:: ต้องเรียกใช้งาน superclass กับ onRestoreInstanceState() methdo เพื่อที่เป็นการ
กำหนดค่าเริ่มต้นให้สามารถกู้คืนข้อมูล state ตามลำดับขั้นของ view ได้


กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ



อ่านต่อที่บทความ









เนื้อหาที่เกี่ยวข้อง









URL สำหรับอ้างอิง





คำแนะนำ และการใช้งาน

สมาชิก กรุณา ล็อกอินเข้าระบบ เพื่อตั้งคำถามใหม่ หรือ ตอบคำถาม สมาชิกใหม่ สมัครสมาชิกได้ที่ สมัครสมาชิก


  • ถาม-ตอบ กรุณา ล็อกอินเข้าระบบ
  • เปลี่ยน


    ( หรือ เข้าใช้งานผ่าน Social Login )







เว็บไซต์ของเราให้บริการเนื้อหาบทความสำหรับนักพัฒนา โดยพึ่งพารายได้เล็กน้อยจากการแสดงโฆษณา โปรดสนับสนุนเว็บไซต์ของเราด้วยการปิดการใช้งานตัวปิดกั้นโฆษณา (Disable Ads Blocker) ขอบคุณครับ