Ben kaydetmek ve bir durumunu geri yüklemek için çalışıyorum Activity
yöntemlerle onSaveInstanceState()
ve onRestoreInstanceState()
.
Sorun, asla onRestoreInstanceState()
yönteme girmemesidir . Biri bana bunun neden olduğunu açıklayabilir mi?
Ben kaydetmek ve bir durumunu geri yüklemek için çalışıyorum Activity
yöntemlerle onSaveInstanceState()
ve onRestoreInstanceState()
.
Sorun, asla onRestoreInstanceState()
yönteme girmemesidir . Biri bana bunun neden olduğunu açıklayabilir mi?
Yanıtlar:
Genellikle eyaletinizi geri yüklersiniz onCreate()
. Onu da geri yüklemek mümkündür onRestoreInstanceState()
, ancak çok yaygın değildir. ( onRestoreInstanceState()
sonra denir onStart()
, oysa onCreate()
önce denir onStart()
.
Değerleri depolamak için put yöntemlerini kullanın onSaveInstanceState()
:
protected void onSaveInstanceState(Bundle icicle) {
super.onSaveInstanceState(icicle);
icicle.putLong("param", value);
}
Değerleri geri yükleyin onCreate()
:
public void onCreate(Bundle icicle) {
if (icicle != null){
value = icicle.getLong("param");
}
}
onRestoreInstanceState()
yalnızca OS tarafından öldürüldükten sonra etkinlik yeniden oluşturulurken çağrılır . Bu durum şu durumlarda olur:
Buna karşılık: etkinliğinizde bulunuyorsanız ve Back
cihazdaki düğmeye basarsanız, etkinliğiniz bitirilir () düzenlenir (yani masaüstü uygulamasından çıktığını düşünün) ve uygulamanızı bir sonraki başlatışınızda "yeni" olarak başlar, yani kaydedildi, çünkü vurduğunuzda bilerek çıktınız Back
.
Diğer bir karışıklık kaynağı ise, bir uygulama odağı kaybettiğinde başka bir uygulamaya odaklandığında, onSaveInstanceState()
ancak uygulamanıza geri döndüğünüzde onRestoreInstanceState()
çağrılamayabileceğinizdir. Bu, orijinal soruda açıklanan durumdur, yani onRestoreInstanceState()
etkinliğinizin hemen hemen "canlı" olduğu için etkinliğinizin başka bir etkinliğin önlendiği dönemde öldürülmediği durumlarda çağrılmaz.
Sonuç olarak, aşağıdakiler için belgelerde belirtildiği gibi onRestoreInstanceState()
:
Çoğu uygulama, durumlarını geri yüklemek için onCreate (Bundle) işlevini kullanır, ancak başlatma işleminin tamamlanmasından sonra burada yapmak veya alt sınıfların varsayılan uygulamanızı kullanıp kullanmayacağınıza karar vermesine izin vermek bazen uygun olabilir. Bu yöntemin varsayılan uygulaması, daha önce onSaveInstanceState (Bundle) tarafından dondurulmuş herhangi bir görünüm durumunun geri yüklemesini gerçekleştirir.
Okuduğum gibi: onRestoreInstanceState()
Alt sınıflamadığınız sürece geçersiz kılmak için bir neden yoktur Activity
ve birisinin alt sınıfınızı alt sınıflandırması beklenir.
Kaydettiğiniz onSaveInstanceState()
durum daha sonra onCreate()
yöntem çağrısında kullanılabilir. Bu nedenle onCreate
(ve Bundle
parametresini) etkinliğinizin durumunu geri yüklemek için kullanın.
Geçici bir çözüm olarak, A etkinliğini başlatmak için kullandığınız Niyet'te korumak istediğiniz verilerle bir paket depolayabilirsiniz.
Intent intent = new Intent(this, ActivityA.class);
intent.putExtra("bundle", theBundledData);
startActivity(intent);
Etkinlik A'nın bunu Etkinlik B'ye geri iletmesi gerekir. Amaç, Etkinlik B'nin onCreate yönteminde alınır.
Intent intent = getIntent();
Bundle intentBundle;
if (intent != null)
intentBundle = intent.getBundleExtra("bundle");
// Do something with the data.
Başka bir fikir, etkinlik durumunu saklamak için bir depo sınıfı oluşturmak ve faaliyetlerinizin her birinin bu sınıfı referans almasını sağlamaktır (tek bir yapı kullanarak mümkündür.) Bununla birlikte, bunu yapmak muhtemelen değerinden daha fazla sorundur.
Ana şey, eğer saklamıyorsanız onSaveInstanceState()
o onRestoreInstanceState()
zaman çağrılmayacaksınız. restoreInstanceState()
Ve arasındaki temel fark budur onCreate()
. Gerçekten bir şey sakladığınızdan emin olun. Büyük ihtimalle bu senin sorunun.
Ön plana başka bir etkinlik geldiğinde her zaman onSaveInstanceState çağrıldığını buldum. Ve onStop da öyle.
Ancak, onRestoreInstanceState öğesi yalnızca onCreate ve onStart da çağrıldığında çağrıldı. Ve onCreate ve onStart her zaman çağrılmadı.
Dolayısıyla, Etkinlik arka plana taşınsa bile Android durum bilgilerini her zaman silmiyor gibi görünüyor. Ancak, durumu güvenli olmak için yaşam döngüsü yöntemlerini çağırır. Bu nedenle, durum silinmezse, Android, gerekli olmadığı için durumu geri yüklemek için yaşam döngüsü yöntemlerini çağırmaz.
Şekil 2 bunu açıklamaktadır.
OnRestoreInstanceState öğesinin her zaman onSaveInstanceState öğesinden sonra çağrılması gerekmez.
Unutmayın: Etkinlik döndürüldüğünde (yönlendirme işlenmediğinde) onRestoreInstanceState her zaman çağrılır veya etkinliğinizi açar ve ardından etkinlik örneğinizin işletim sistemi tarafından bellekten silinmesi için diğer uygulamaları açar.
Kaydedilen örnek durumunu kullanarak etkinlik kullanıcı arabirimi durumunu geri yükleme belgelerinden şöyle belirtilir:
OnCreate () sırasında durumu geri yüklemek yerine, sistemin onStart () yönteminden sonra çağırdığı onRestoreInstanceState () yöntemini uygulamayı seçebilirsiniz. Sistem onRestoreInstanceState () yöntemini yalnızca geri yüklenecek kayıtlı bir durum varsa çağırır, bu nedenle Paketin boş olup olmadığını kontrol etmeniz gerekmez :
IMO, bunu onCreate'de kontrol etmekten daha açık bir yoldur ve tek sorumluluk ilkesine daha iyi uyuyor.
Benim durumumda, onRestoreInstanceState
cihaz yönünü değiştirdikten sonra aktivite yeniden yapılandırıldığında çağrıldı. onCreate(Bundle)
önce çağrıldı, ancak pakette ayarladığım anahtar / değerler yoktu onSaveInstanceState(Bundle)
.
Hemen sonra, onRestoreInstanceState(Bundle)
doğru anahtar / değerlere sahip bir paket ile çağrıldı.
Ben sadece bu koştu ve belgelerin cevabım olduğunu fark ettim:
"Bu işlev asla boş durumla çağrılmaz."
Benim durumumda, onRestoreInstanceState'in neden ilk örneklemede çağrılmadığını merak ediyordum. Bu aynı zamanda hiçbir şey depolamazsanız, görüşünüzü yeniden yapılandırmaya gittiğinizde çağrılmayacağı anlamına gelir.
Bunu yapabilirim (üzgünüm c # java değil ama sorun değil ...):
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);
}
VE SONUÇ İÇİN FAALİYETİNİZDE
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();
}
EN SONUNDA
protected override void OnActivityResult(int iRequestCode, Android.App.Result oResultCode, Intent oIntent)
{
base.OnActivityResult (iRequestCode, oResultCode, oIntent);
iValue = oIntent.Extras.GetInt("MYVALUE", -1); //=> 1234567890
}