เมื่อใดที่เรียกว่า onSaveInstanceState () และ onRestoreInstanceState ()


102

รูปต่อไปนี้ (จากเอกสารอย่างเป็นทางการ ) อธิบายวงจรชีวิตที่รู้จักกันดีของกิจกรรม Android:

ใส่คำอธิบายภาพที่นี่

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

ใส่คำอธิบายภาพที่นี่

ฉันทราบดีว่าonSaveInstanceState()จะไม่ถูกเรียกเสมอไปเมื่อกิจกรรมกำลังจะถูกทำลาย ตัวอย่างเช่นหากถูกทำลายเนื่องจากผู้ใช้กดปุ่ม "ย้อนกลับ" สถานะกิจกรรมจะไม่ถูกเก็บรักษาไว้ แต่ในกรณีที่สถานะถูกบันทึกและกู้คืนและonSaveInstanceState()/ onRestoreInstanceState()ได้รับการเรียกมันถูกเรียกเมื่อใด

ยกตัวอย่างเช่นตามตัวเลขดังกล่าวข้างต้นonRestoreInstanceState()อาจจะเรียกว่าก่อนonStart()หรือหลังonStart()แต่ก่อนหรือหลังonResume() ในทำนองเดียวกันเป็นไปได้หลายที่มีอยู่สำหรับonResume() onSaveInstanceState()พวกเขาเรียกว่าเมื่อไหร่กันแน่?

ตามหลักการแล้วสิ่งที่ฉันต้องการคือดูแผนภาพรวมที่แสดงสถานะวงจรชีวิตของกิจกรรมและวิธีการบันทึก / กู้คืนหากมีอยู่


ได้รับคำตอบสุดท้ายจากเอกสารอย่างเป็นทางการของ Android ที่เรียกว่า onSaveInstanceState () ระหว่าง onPause () และ onStop ()
Rishi

1
@Rishi ช่วยส่งลิงค์ไปยังเอกสารนั้นได้ไหม
Luis Mendo


อ่านบันทึกสถานะกิจกรรมของคุณย่อหน้าที่นั่น
Rishi

ว่าถูกต้องหรือไม่โปรดชี้แจง
ฤๅษี

คำตอบ:


107

ตามเอกสารประกอบ :

เป็นโมฆะ onRestoreInstanceState (Bundle savedInstanceState)

วิธีการนี้เรียกว่าระหว่างและonStart()onPostCreate(Bundle)

เป็นโมฆะ onSaveInstanceState (Bundle outState)

หากเรียกวิธีนี้จะเกิดขึ้นหลังจาก onStop () สำหรับแอปพลิเคชันที่กำหนดเป้าหมายแพลตฟอร์มที่เริ่มต้นด้วย Build.VERSION_CODES.P สำหรับแอปพลิเคชันที่กำหนดเป้าหมายแพลตฟอร์มเวอร์ชันก่อนหน้าวิธีนี้จะเกิดขึ้นก่อน onStop () และไม่มีการรับประกันว่าจะเกิดขึ้นก่อนหรือหลัง onPause ()


1
ขอบคุณ. คุณช่วยกรุณาให้ลิงค์ไปยังเอกสารประกอบได้หรือไม่?
Luis Mendo

คุณไปแล้วและฉันไม่คิดว่าจะมีอะไรอีกระหว่าง onStart () และ onPostCreate () ดังนั้น onRestoreInstanceState () จึงถูกกำหนดไว้อย่างดีในห่วงโซ่
Steve M

ขอบคุณมาก. นี่เป็นการชี้แจงปัญหา
Luis Mendo

1
@SteveM "ไม่มีการรับประกันว่าจะเกิดขึ้นก่อนหรือหลัง onPause ()" หมายความว่าหากเราพยายามเข้าถึงมุมมอง (เพื่อรับค่าบางอย่างเพื่อบันทึกเช่นดัชนีจากมุมมองรายการ) เราอาจพบ NullPointerExceptions หรือไม่
Tiago

3
จากนั้นสิ่งที่แนะนำคือการบันทึกโครงสร้างข้อมูลใน onPause และเรียกคืนใน onResume แทนใน onSaveInstanceState และ onRestoreInstanceState?
Gödel77

19

ตามdoc1และdoc2

onSaveInstanceState

ก่อนที่จะมี Honeycomb กิจกรรมต่างๆไม่ถือว่าฆ่าได้จนกว่าจะหยุดชั่วคราวซึ่งหมายความว่า onSaveInstanceState () ถูกเรียกทันทีก่อน onPause () อย่างไรก็ตามเริ่มต้นด้วย Honeycomb กิจกรรมจะถือว่าสามารถฆ่าได้ก็ต่อเมื่อหยุดแล้วซึ่งหมายความว่า onSaveInstanceState () จะถูกเรียกก่อน onStop () แทนที่จะเป็นก่อน onPause ()

onRestoreInstanceState

วิธีนี้เรียกว่าระหว่าง onStart () และ onPostCreate (Bundle) เมื่อกิจกรรมกำลังถูกเตรียมใช้งานใหม่จากสถานะที่บันทึกไว้ก่อนหน้านี้


ชอบวิธีที่คุณอธิบายสถานการณ์ใน Android เวอร์ชันต่างๆ
Jimit Patel

14

นอกเหนือจากคำตอบที่โพสต์แล้วยังมีการเปลี่ยนแปลงเล็กน้อยใน Android P ซึ่ง ได้แก่ :

เป็นโมฆะ onSaveInstanceState (Bundle outState)

ถ้าเรียกว่าวิธีการนี้จะเกิดขึ้นหลังจากที่ onStop()สำหรับการใช้งานแพลตฟอร์มการกำหนดเป้าหมายที่เริ่มต้นด้วยP สำหรับการใช้งานการกำหนดเป้าหมายรุ่นแพลตฟอร์มก่อนหน้านี้วิธีการนี้จะเกิดขึ้นก่อนและมีการค้ำประกันเกี่ยวกับว่ามันจะเกิดขึ้นก่อนหรือหลังไม่มีonStop()onPause()

ที่มา: docs

สาเหตุที่ทำให้เกิดการเปลี่ยนแปลงนี้มีคำตอบดังนี้

... ดังนั้นแอปพลิเคชันสามารถทำธุรกรรมส่วนย่อยได้อย่างปลอดภัยonStop()และจะสามารถบันทึกสถานะถาวรได้ในภายหลัง

ที่มา: docs


สวัสดีความคิดเห็นที่ดี คุณรู้หรือไม่ว่าแอปจะทำงานอย่างไรที่กำหนดเป้าหมาย P แต่ทำงานบน API ที่ต่ำกว่า? เหมือนกับแอปที่กำหนดเป้าหมาย API ที่ต่ำกว่าหรือจะสอดคล้องกันทั้ง API และคงพฤติกรรม "การกำหนดเป้าหมาย API" ไว้
Filipkowicz

@Filipkowicz Do you know how will behave app that target P but runs on lower api?ตราบใดที่แอปกำลังทำงานบนพูดว่า M ดังนั้นเวอร์ชันของ Android ที่อุปกรณ์นี้ไม่มีการเปลี่ยนแปลงจะถูกนำมาใช้ใน P ซึ่งหมายความว่าไม่ว่าคุณจะระบุเป้าหมายไว้ก็ตาม แต่Pคุณจะไม่เห็น แตกต่างกันสำหรับอุปกรณ์ pre-P หวังว่านี่จะตอบคำถามของคุณ
azizbekian

วันนี้ฉันรู้สึกผ่อนคลายมากหลังจากอ่านคำตอบนี้เพราะฉันกำลังทำหลักสูตรฟรีสำหรับ Android บน Udacity และพวกเขายังคงมีแบบฝึกหัดเวอร์ชันเก่าซึ่งระบุไว้ในบทที่ 5 แบบฝึกหัด 8 ว่าวิธีการ onStop และ onDestroy ไม่ควรมีอยู่ใน textView ที่แสดง แต่ฉันไม่รู้ว่าเป็นสำหรับ Android เวอร์ชันเก่าและฉันกำลังเรียกใช้แอปพลิเคชันของฉันบน android pie และได้รับวิธี onStop ใน textView ของฉัน ขอบคุณมาก. ในที่สุดก็รู้สึกดี.
Sandhu

6

นี่เป็นข้อมูลเพิ่มเติมสำหรับonSaveInstanceState (Bundle)

จากเอกสาร

อย่าสับสนวิธีนี้กับการเรียกกลับวงจรชีวิตของกิจกรรมเช่น onPause () ซึ่งจะเรียกเสมอเมื่อกิจกรรมถูกวางไว้เบื้องหลังหรือระหว่างทางไปสู่การทำลายหรือ onStop () ซึ่งเรียกก่อนการทำลาย ตัวอย่างหนึ่งของเมื่อเรียกใช้ onPause () และ onStop () และไม่ใช่วิธีนี้คือเมื่อผู้ใช้ย้อนกลับจากกิจกรรม B ไปยังกิจกรรม A: ไม่จำเป็นต้องเรียก onSaveInstanceState (Bundle) บน B เนื่องจากอินสแตนซ์นั้นจะไม่ถูกเรียกคืน ดังนั้นระบบจึงหลีกเลี่ยงการเรียกมัน ตัวอย่างเมื่อเรียก onPause () และไม่ได้อยู่บนSaveInstanceState (Bundle) คือเมื่อกิจกรรม B ถูกเรียกใช้หน้ากิจกรรม A: ระบบอาจหลีกเลี่ยงการเรียก onSaveInstanceState (Bundle) ในกิจกรรม A หากไม่ถูกฆ่าในช่วงชีวิตของ B ตั้งแต่ สถานะของอินเทอร์เฟซผู้ใช้ของ A จะยังคงเหมือนเดิม

ดังนั้นจึงเป็นการใช้งานเริ่มต้นสำหรับ ..

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


0
String activityState;
@Override 
public void onCreate(Bundle savedInstanceState) {
// call the super class onCreate to complete the creation of activity like 
// the view hierarchy 
super.onCreate(savedInstanceState);

// recovering the instance state 
if (savedInstanceState != null) {
     activityState = savedInstanceState.getString(STATE_KEY);
 } 

   setContentView(R.layout.main_activity);
   mTextView = (TextView) findViewById(R.id.text_view);
} 

// การเรียกกลับนี้จะเรียกก็ต่อเมื่อมีอินสแตนซ์ที่บันทึกไว้ก่อนหน้านี้โดยใช้ // onSaveInstanceState () เรากู้คืนสถานะบางอย่างใน onCreate () ในขณะที่เราสามารถเลือกเรียกคืน // สถานะอื่นได้ที่นี่ซึ่งอาจใช้งานได้หลังจากที่ onStart () เสร็จสิ้น // บันเดิลที่บันทึกไว้จะเหมือนกับที่ใช้ใน onCreate ()

@Override 
public void onRestoreInstanceState(Bundle savedInstanceState) {
 mTextView.setText(savedInstanceState.getString(STATE_KEY));
  } 


// invoked when the activity may be temporarily destroyed, save the instance 
//state here 
//this method will be called before onstop

@Override 
 public void onSaveInstanceState(Bundle outState) {
    outState.putString(STATE_KEY, activityState);

    // call superclass to save any view hierarchy 
    super.onSaveInstanceState(outState);
} 

ขอโทษนะสิ่งนี้จะตอบคำถามได้อย่างไรว่าเมธอดบันทึก / กู้คืนถูกเรียกว่าอย่างไร
Luis Mendo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.