ฉันพยายามที่จะบันทึกและเรียกคืนสถานะของนั้นActivity
โดยใช้วิธีการและonSaveInstanceState()
onRestoreInstanceState()
ปัญหาคือมันไม่เคยเข้าonRestoreInstanceState()
วิธี มีใครอธิบายให้ฉันฟังได้ไหมว่าเพราะอะไร
ฉันพยายามที่จะบันทึกและเรียกคืนสถานะของนั้นActivity
โดยใช้วิธีการและonSaveInstanceState()
onRestoreInstanceState()
ปัญหาคือมันไม่เคยเข้าonRestoreInstanceState()
วิธี มีใครอธิบายให้ฉันฟังได้ไหมว่าเพราะอะไร
คำตอบ:
onCreate()
โดยปกติแล้วคุณเรียกคืนสถานะของคุณ เป็นไปได้ที่จะกู้คืนในonRestoreInstanceState()
เช่นกัน แต่ก็ไม่ธรรมดา ( onRestoreInstanceState()
เรียกว่าหลังจากonStart()
ในขณะที่เรียกว่าก่อนที่จะonCreate()
onStart()
ใช้วิธีการวางเพื่อเก็บค่าในonSaveInstanceState()
:
protected void onSaveInstanceState(Bundle icicle) {
super.onSaveInstanceState(icicle);
icicle.putLong("param", value);
}
และเรียกคืนค่าในonCreate()
:
public void onCreate(Bundle icicle) {
if (icicle != null){
value = icicle.getLong("param");
}
}
onRestoreInstanceState()
ถูกเรียกใช้เฉพาะเมื่อสร้างกิจกรรมใหม่หลังจากที่ระบบปฏิบัติการนั้นถูกฆ่า สถานการณ์ดังกล่าวเกิดขึ้นเมื่อ:
ในทางตรงกันข้าม: หากคุณอยู่ในกิจกรรมของคุณและคุณกดBack
ปุ่มบนอุปกรณ์กิจกรรมของคุณจะเสร็จสิ้น () ed (เช่นคิดว่ามันเป็นการออกจากแอปพลิเคชันเดสก์ท็อป) และในครั้งต่อไปที่คุณเริ่มแอป Back
บันทึกรัฐเพราะคุณจงใจเดินออกมาจากมันเมื่อคุณกด
แหล่งที่มาของความสับสนอื่น ๆ คือเมื่อมีการเรียกแอพโฟกัสไปที่แอพอื่นonSaveInstanceState()
แต่เมื่อคุณนำทางกลับไปที่แอพของคุณonRestoreInstanceState()
อาจไม่ถูกเรียก นี่เป็นกรณีที่อธิบายไว้ในคำถามเดิมเช่นหากกิจกรรมของคุณไม่ถูกฆ่าในช่วงเวลาที่กิจกรรมอื่น ๆ อยู่ข้างหน้าonRestoreInstanceState()
จะไม่ถูกเรียกเนื่องจากกิจกรรมของคุณค่อนข้าง "มีชีวิตชีวา"
ทั้งหมดตามที่ระบุไว้ในเอกสารประกอบสำหรับonRestoreInstanceState()
:
การใช้งานส่วนใหญ่จะใช้ onCreate (Bundle) เพื่อกู้คืนสถานะของพวกเขา แต่บางครั้งก็สะดวกที่จะทำที่นี่หลังจากการเริ่มต้นทั้งหมดเสร็จสิ้นหรืออนุญาตให้คลาสย่อยตัดสินใจว่าจะใช้การเริ่มต้นใช้งานของคุณหรือไม่ การใช้งานเริ่มต้นของวิธีนี้ทำการคืนค่าสถานะมุมมองใด ๆ ที่ก่อนหน้านี้ถูกตรึงโดย onSaveInstanceState (Bundle)
ตามที่ฉันได้อ่าน: ไม่มีเหตุผลใดที่จะลบล้างonRestoreInstanceState()
ยกเว้นว่าคุณกำลังทำคลาสย่อยอยู่Activity
และคาดว่าจะมีใครบางคนจะทำคลาสย่อยของคุณให้เป็นคลาสย่อย
สถานะที่คุณบันทึกที่onSaveInstanceState()
มีอยู่ในภายหลังที่onCreate()
วิธีการภาวนา ดังนั้นใช้onCreate
(และBundle
พารามิเตอร์) เพื่อคืนสถานะกิจกรรมของคุณ
คุณสามารถจัดเก็บบันเดิลกับข้อมูลที่คุณต้องการเก็บไว้ใน Intent ที่คุณใช้เพื่อเริ่มกิจกรรม A
Intent intent = new Intent(this, ActivityA.class);
intent.putExtra("bundle", theBundledData);
startActivity(intent);
กิจกรรม A จะต้องผ่านสิ่งนี้กลับไปที่กิจกรรม B คุณจะต้องดึงความตั้งใจในวิธีการ onCreate ของกิจกรรม B
Intent intent = getIntent();
Bundle intentBundle;
if (intent != null)
intentBundle = intent.getBundleExtra("bundle");
// Do something with the data.
อีกแนวคิดหนึ่งคือการสร้างคลาสที่เก็บข้อมูลเพื่อเก็บสถานะกิจกรรมและให้แต่ละกิจกรรมอ้างอิงคลาสนั้น (เป็นไปได้โดยใช้โครงสร้างซิงเกิล) แม้ว่าการทำเช่นนั้นอาจเป็นปัญหามากกว่าที่ควรจะเป็น
สิ่งสำคัญคือถ้าคุณไม่เก็บไว้ในonSaveInstanceState()
นั้นonRestoreInstanceState()
จะไม่ถูกเรียก นี่คือความแตกต่างที่สำคัญระหว่างและrestoreInstanceState()
onCreate()
ตรวจสอบให้แน่ใจว่าคุณเก็บอะไรบางอย่างจริงๆ เป็นไปได้มากว่านี่เป็นปัญหาของคุณ
ฉันพบว่า onSaveInstanceState จะถูกเรียกเสมอเมื่อมีกิจกรรมอื่นมาถึงเบื้องหน้า และดังนั้นจึงเป็นบนหยุด
อย่างไรก็ตาม onRestoreInstanceState ถูกเรียกเมื่อ onCreate และ onStart ถูกเรียกด้วย และ onCreate และ onStart ก็ไม่ได้ถูกเรียกเสมอ
ดังนั้นดูเหมือนว่า Android จะไม่ลบข้อมูลสถานะเสมอแม้ว่ากิจกรรมจะย้ายไปที่พื้นหลัง อย่างไรก็ตามมันเรียกวิธีการวงจรชีวิตเพื่อบันทึกสถานะเพียงเพื่อความปลอดภัย ดังนั้นหากสถานะไม่ถูกลบออก Android จะไม่เรียกวิธีการวงจรชีวิตเพื่อเรียกคืนสถานะเนื่องจากไม่จำเป็น
รูปที่ 2อธิบายสิ่งนี้
ฉันคิดว่ากระทู้นี้ค่อนข้างเก่า ฉันเพียงแค่พูดถึงอีกกรณีหนึ่งที่จะได้รับการเรียกว่าเป็นเมื่อคุณเรียกonSaveInstanceState()
Activity.moveTaskToBack(boolean nonRootActivity)
หากคุณมีการจัดการกิจกรรมของการเปลี่ยนแปลงการวางแนวทางด้วยandroid:configChanges="orientation|screenSize"
และonConfigurationChanged(Configuration newConfig)
, onRestoreInstanceState()
จะไม่ถูกเรียก
ไม่จำเป็นว่า onRestoreInstanceState จะถูกเรียกหลังจาก onSaveInstanceState เสมอ
โปรดทราบว่า: onRestoreInstanceState จะถูกเรียกเสมอเมื่อมีการหมุนกิจกรรม (เมื่อไม่มีการจัดการการวางแนว) หรือเปิดกิจกรรมของคุณแล้วเปิดแอปอื่น ๆ เพื่อให้ระบบดำเนินการอินสแตนซ์กิจกรรมของคุณจากหน่วยความจำ
จากเอกสารการคืนค่าสถานะกิจกรรม UI โดยใช้สถานะอินสแตนซ์ที่บันทึกไว้จะมีการระบุเป็น:
แทนที่จะเรียกคืนสถานะระหว่าง onCreate () คุณสามารถเลือกใช้ onRestoreInstanceState () ซึ่งระบบจะเรียกใช้หลังจากเมธอด onStart () ระบบเรียกใช้ onRestoreInstanceState () เฉพาะเมื่อมีสถานะที่บันทึกไว้เพื่อกู้คืนดังนั้นคุณไม่จำเป็นต้องตรวจสอบว่า Bundle เป็นโมฆะหรือไม่ :
IMO นี่เป็นวิธีที่ชัดเจนกว่าการตรวจสอบที่ onCreate และเหมาะกับหลักการความรับผิดชอบเดียว
ในกรณีของฉันonRestoreInstanceState
ถูกเรียกเมื่อกิจกรรมถูกสร้างขึ้นใหม่หลังจากเปลี่ยนการวางแนวอุปกรณ์ onCreate(Bundle)
ก็เรียกว่าเป็นครั้งแรก แต่กำไม่ได้มีคีย์ / onSaveInstanceState(Bundle)
ค่าที่ผมตั้งด้วย
หลังจากนั้นonRestoreInstanceState(Bundle)
ถูกเรียกพร้อมกับบันเดิลที่มีคีย์ / ค่าที่ถูกต้อง
ฉันเพิ่งพบปัญหานี้และพบว่าเอกสารมีคำตอบของฉัน:
"ฟังก์ชั่นนี้จะไม่ถูกเรียกด้วยสถานะว่าง"
ในกรณีของฉันฉันสงสัยว่าทำไม onRestoreInstanceState จึงไม่ถูกเรียกใช้ในการเริ่มต้นเริ่มต้น นี่ก็หมายความว่าถ้าคุณไม่เก็บอะไรมันจะไม่ถูกเรียกเมื่อคุณไปสร้างมุมมองใหม่
ฉันสามารถทำเช่นนั้นได้ (ขออภัยที่ไม่ใช่ c # ไม่ใช่ java แต่ไม่ใช่ปัญหา ... ):
private int iValue = 1234567890;
function void MyTest()
{
Intent oIntent = new Intent (this, typeof(Camera2Activity));
Bundle oBundle = new Bundle();
oBundle.PutInt("MYVALUE", iValue); //=> 1234567890
oIntent.PutExtras (oBundle);
iRequestCode = 1111;
StartActivityForResult (oIntent, 1111);
}
และในกิจกรรมของคุณเพื่อผลลัพธ์
private int iValue = 0;
protected override void OnCreate(Bundle bundle)
{
Bundle oBundle = Intent.Extras;
if (oBundle != null)
{
iValue = oBundle.GetInt("MYVALUE", 0);
//=>1234567890
}
}
private void FinishActivity(bool bResult)
{
Intent oIntent = new Intent();
Bundle oBundle = new Bundle();
oBundle.PutInt("MYVALUE", iValue);//=>1234567890
oIntent.PutExtras(oBundle);
if (bResult)
{
SetResult (Result.Ok, oIntent);
}
else
SetResult(Result.Canceled, oIntent);
GC.Collect();
Finish();
}
ในที่สุด
protected override void OnActivityResult(int iRequestCode, Android.App.Result oResultCode, Intent oIntent)
{
base.OnActivityResult (iRequestCode, oResultCode, oIntent);
iValue = oIntent.Extras.GetInt("MYVALUE", -1); //=> 1234567890
}