onSaveInstanceState () ve onRestoreInstanceState ()


138

Ben kaydetmek ve bir durumunu geri yüklemek için çalışıyorum Activityyöntemlerle onSaveInstanceState()ve onRestoreInstanceState().

Sorun, asla onRestoreInstanceState()yönteme girmemesidir . Biri bana bunun neden olduğunu açıklayabilir mi?


1
@Nitin: bağlantıyı paylaştığın için teşekkürler ... bu benim için birkaç şeyi temizledi +1
Taliadon

2
@NitinBansal bağlantı öldü.
ashishdhiman2007

Yanıtlar:


191

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");
  }
}

2
sorun, A aktivitesine geri dönmek için startActivity'yi kullanmam.
BlaBRA

5
Doğru anlarsam, yaptığınız şey budur: B'den startActivity (A) diyoruz. Sonra A'dan B'ye geri dönmek için finish () öğesini çağırırsınız. Bu durumda, İlk etkinliğiniz, B yok edilmeyecektir ve ne onCreate () ne de onRestoreInstanceState () yöntemi çağrılmayacaktır. Bu yöntemler yalnızca gerektiğinde, yani bir etkinliğin yok edildiği ve sistem tarafından yeniden oluşturulması gerektiğinde çağrılır.
Robert

4
İlk faaliyetiniz olan B'nin düşük bellek koşulları nedeniyle yok olabileceğini eklemeliyim. Bu, onCreate ve onRestoreInstanceState öğelerini tetikler.
Robert

1
erikb, evet, B etkinliği sürdürülecek veya işletim sisteminin geri alması, yeniden oluşturulması ve yeniden başlatılması durumunda.
Robert


149

onRestoreInstanceState()yalnızca OS tarafından öldürüldükten sonra etkinlik yeniden oluşturulurken çağrılır . Bu durum şu durumlarda olur:

  • cihazın yönelimi değişir (etkinliğiniz yok edilir ve yeniden oluşturulur).
  • önünüzde başka bir etkinlik daha var ve bir noktada işletim sistemi belleği boşaltmak için etkinliğinizi öldürüyor (örneğin). Bir dahaki sefere faaliyetinizi başlattığınızda onRestoreInstanceState () yöntemi çağrılır.

Buna karşılık: etkinliğinizde bulunuyorsanız ve Backcihazdaki 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 Activityve birisinin alt sınıfınızı alt sınıflandırması beklenir.


3
Evet, bu doğru gibi görünüyor, ama berbat. imo aynı zamanda başka bir etkinliğin etkinliğine geri dönerken de çalıştırılmalıdır. buna ihtiyacınız olan birçok durum vardır.
masi

4
@masi, kullanıcı buna geri döndüğünde (başka bir etkinlikten) Etkinlik'te çağrılan başka yöntemler de vardır. OnSave / RestoreInstanceState () başka bir belirli amaç için kullanılır, hepsi bu.
superjos

8

Kaydettiğiniz onSaveInstanceState()durum daha sonra onCreate()yöntem çağrısında kullanılabilir. Bu nedenle onCreate(ve Bundleparametresini) etkinliğinizin durumunu geri yüklemek için kullanın.


4

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.


3

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.


1
OnSaveInstanceState () içinde hiçbir şey saklamasanız bile onRestoreInstanceState ()
çağrılır

3

Ö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.


2

Bu konu oldukça eski olduğunu düşünüyorum. Sadece başka bir durumdan bahsediyorum, bu onSaveInstanceState()da çağrılacak Activity.moveTaskToBack(boolean nonRootActivity).


1

Birlikte etkinliğin oryantasyon değişiklikleri ele yapıyorsanız android:configChanges="orientation|screenSize"ve onConfigurationChanged(Configuration newConfig), onRestoreInstanceState()denilen edilmeyecektir.


1

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.


1

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 :

resim açıklamasını buraya girin

resim açıklamasını buraya girin

IMO, bunu onCreate'de kontrol etmekten daha açık bir yoldur ve tek sorumluluk ilkesine daha iyi uyuyor.


0

Benim durumumda, onRestoreInstanceStatecihaz 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ı.



0

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
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.