onSaveInstanceState () और onRestoreInstanceState ()


138

मैं Activityतरीकों का उपयोग करके राज्य को बचाने और पुनर्स्थापित करने की कोशिश कर रहा हूं onSaveInstanceState()और onRestoreInstanceState()

समस्या यह है कि यह कभी भी onRestoreInstanceState()विधि में प्रवेश नहीं करता है । क्या कोई मुझे समझा सकता है कि ऐसा क्यों है?


1
@ नितिन: लिंक साझा करने के लिए धन्यवाद ... यह मेरे लिए कुछ चीजें साफ कर चुका है +1
टालियाडॉन

2
@NitinBansal लिंक मृत है।
ashishdhiman2007

जवाबों:


191

आमतौर पर आप अपने राज्य को बहाल करते हैं 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");
  }
}

2
समस्या यह है कि मैं गतिविधि ए पर लौटने के लिए startActivity का उपयोग करता हूं। जब गतिविधि B पर लौट रहा हूं, तो वस्तु अशक्त है।
ब्लाबरा

5
अगर मैं सही तरीके से समझूं, तो आप यही कर रहे हैं: B से आप startActivity (A) कहते हैं। फिर ए से आप कॉल खत्म () बी वापस करने के लिए सही है? उस स्थिति में आपकी पहली गतिविधि, B नष्ट नहीं हुई होगी, और न ही OnCreate () और न ही onRestoreInstanceState () को बुलाया जाएगा। इन विधियों को केवल तब बुलाया जाता है जब जरूरत होती है, जब एक गतिविधि नष्ट हो गई है और सिस्टम द्वारा इसे फिर से बनाने की आवश्यकता है।
रॉबर्ट

4
मुझे यह जोड़ना चाहिए कि आपकी पहली गतिविधि, बी, कम स्मृति स्थितियों के कारण नष्ट हो सकती है। यह onCreate और onRestoreInstanceState को ट्रिगर करेगा।
रॉबर्ट

1
erikb, हाँ, गतिविधि B को फिर से शुरू किया जाएगा, या यदि OS ने इसे पुनः प्राप्त किया है, फिर से बनाया है और फिर से शुरू किया है।
रॉबर्ट


149

onRestoreInstanceState()OS द्वारा मारे जाने के बाद गतिविधि को फिर से बनाने के लिए ही कहा जाता है । ऐसी स्थिति तब होती है जब:

  • डिवाइस परिवर्तन का उन्मुखीकरण (आपकी गतिविधि नष्ट हो जाती है और पुनः निर्मित होती है)।
  • आपके सामने एक और गतिविधि है और कुछ बिंदु पर ओएस आपकी गतिविधि को मुक्त स्मृति (उदाहरण के लिए) के क्रम में मारता है। अगली बार जब आप अपनी गतिविधि शुरू करते हैं onRestoreInstanceState () कहा जाएगा।

इसके विपरीत: यदि आप अपनी गतिविधि में हैं और आप Backडिवाइस पर बटन दबाते हैं, तो आपकी गतिविधि समाप्त () एड (यानी इसे डेस्कटॉप एप्लिकेशन से बाहर निकलने के बारे में सोचें) और अगली बार जब आप अपना ऐप शुरू करते हैं तो यह "फ्रेश" शुरू होता है, अर्थात बिना राज्य को बचाया क्योंकि आपने जानबूझकर इसे मारा जब आप बाहर निकले Back

भ्रम का अन्य स्रोत यह है कि जब कोई ऐप किसी अन्य ऐप पर ध्यान केंद्रित करता onSaveInstanceState()है तो उसे कॉल किया जाता है लेकिन जब आप अपने ऐप पर वापस जाते onRestoreInstanceState()हैं तो उसे कॉल नहीं किया जा सकता है। यह मूल प्रश्न में वर्णित मामला है, अर्थात यदि आपकी गतिविधि उस अवधि के दौरान नहीं मारी गई थी जब दूसरी गतिविधि सामने थी, तो onRestoreInstanceState()उसे नहीं बुलाया जाएगा क्योंकि आपकी गतिविधि बहुत "जीवित" है।

सभी के लिए, जैसा कि प्रलेखन में कहा गया है onRestoreInstanceState():

अधिकांश कार्यान्वयन बस अपने राज्य को पुनर्स्थापित करने के लिए onCreate (बंडल) का उपयोग करेंगे, लेकिन यह कभी-कभी सुविधाजनक है कि यह सभी इनिशियलाइजेशन के बाद यहां किया गया है या उपवर्गों को यह तय करने की अनुमति देने के लिए कि क्या आपके डिफ़ॉल्ट कार्यान्वयन का उपयोग करना है। इस पद्धति का डिफ़ॉल्ट कार्यान्वयन किसी भी दृश्य स्थिति की पुनर्स्थापना करता है जो पहले onSaveInstanceState (बंडल) द्वारा जमे हुए थे।

जैसा कि मैंने इसे पढ़ा: ओवरराइड करने का कोई कारण नहीं है onRestoreInstanceState()जब तक कि आप उपवर्ग नहीं कर रहे हों Activityऔर यह उम्मीद की जाती है कि कोई व्यक्ति आपके वर्ग को उपवर्ग में ले जाएगा।


3
यह सही लगता है, लेकिन यह बेकार है। imo इसे किसी अन्य गतिविधि से गतिविधि पर लौटने पर भी चलाया जाना चाहिए। ऐसी बहुत सी परिस्थितियाँ हैं जहाँ आपको इसकी आवश्यकता है।
मासी

4
@masi पहले से ही गतिविधि पर लागू अन्य तरीके हैं जब उपयोगकर्ता इसे (किसी अन्य गतिविधि से) लौटाता है। OnSave / RestoreInstanceState () का उपयोग किसी अन्य विशिष्ट उद्देश्य के लिए किया जाता है, बस।
सुपरजोस

8

जिस राज्य को आप बचाते हैं, onSaveInstanceState()वह बाद में onCreate()विधि आह्वान पर उपलब्ध है । इसलिए अपनी गतिविधि की स्थिति को पुनर्स्थापित करने के लिए onCreate(और इसके Bundleपैरामीटर) का उपयोग करें।


4

वर्कअराउंड के रूप में, आप एक्टिविटी शुरू करने के लिए आपके द्वारा उपयोग किए जाने वाले इरादे में बनाए रखने वाले डेटा के साथ एक बंडल स्टोर कर सकते हैं।

Intent intent = new Intent(this, ActivityA.class);
intent.putExtra("bundle", theBundledData);
startActivity(intent);

एक्टिविटी ए को एक्टिविटी बी में वापस भेजना होगा। आप एक्टिविटी बी के ऑनक्रिट विधि में इरादे को पुनः प्राप्त करेंगे।

Intent intent = getIntent();
Bundle intentBundle;
if (intent != null)
    intentBundle = intent.getBundleExtra("bundle");
// Do something with the data.

एक अन्य विचार गतिविधि राज्य को संग्रहीत करने के लिए एक रिपॉजिटरी वर्ग बनाने और आपकी प्रत्येक गतिविधि का संदर्भ है कि क्लास (एक सिंगलटन संरचना का उपयोग करके संभव है।) हालांकि, ऐसा करना संभवतः इसके लायक होने की तुलना में अधिक परेशानी है।


3

मुख्य बात यह है कि यदि आप में स्टोर नहीं करते है onSaveInstanceState()तो onRestoreInstanceState()कहा जाता है नहीं किया जाएगा। यह restoreInstanceState()और के बीच मुख्य अंतर है onCreate()। सुनिश्चित करें कि आप वास्तव में कुछ स्टोर करते हैं। सबसे अधिक संभावना है कि यह आपकी समस्या है।


1
OnRestoreInstanceState () कहा जाएगा, भले ही आप OnSaveInstanceState () में कुछ भी स्टोर न करें
abh22ishek

3

मैंने पाया कि जब कोई अन्य गतिविधि अग्रभूमि में आती है तो onSaveInstanceState को हमेशा कहा जाता है। और ऐसा ही onStop है।

हालाँकि, onRestoreInstanceState को केवल तभी कहा जाता था जब onCreate और onStart को भी बुलाया जाता था। और, onCreate और onStart को हमेशा नहीं बुलाया गया।

तो ऐसा लगता है कि गतिविधि को पृष्ठभूमि में ले जाने पर भी Android हमेशा राज्य की जानकारी को नष्ट नहीं करता है। हालाँकि, यह केवल सुरक्षित रहने के लिए राज्य को बचाने के लिए जीवनचक्र विधियों को कॉल करता है। इस प्रकार, यदि राज्य को हटाया नहीं जाता है, तो राज्य को पुनर्स्थापित करने के लिए एंड्रॉइड जीवनचक्र के तरीकों को नहीं बुलाता है क्योंकि उन्हें ज़रूरत नहीं है।

चित्र 2 इसका वर्णन करता है।


2

मुझे लगता है कि यह धागा काफी पुराना था। मैं सिर्फ एक अन्य मामले का उल्लेख करता हूं, जिसे onSaveInstanceState()भी कॉल किया जाएगा, जब आप कॉल करेंगे Activity.moveTaskToBack(boolean nonRootActivity)


1

यदि आप गतिविधि के अभिविन्यास में परिवर्तन कर रहे हैं android:configChanges="orientation|screenSize"और onConfigurationChanged(Configuration newConfig), onRestoreInstanceState()को नहीं बुलाया जाएगा।


1

यह आवश्यक नहीं है कि onRestoreInstanceState को onSaveInstanceState के बाद हमेशा बुलाया जाएगा।

ध्यान दें: onRestoreInstanceState को हमेशा कहा जाता है, जब गतिविधि को घुमाया जाता है (जब अभिविन्यास को नियंत्रित नहीं किया जाता है) या अपनी गतिविधि खोलें और फिर अन्य ऐप खोलें ताकि ओएस द्वारा मेमोरी से आपकी गतिविधि का उदाहरण साफ़ हो जाए।


1

सहेजे गए इंस्टेंस राज्य का उपयोग करके प्रलेखन पुनर्स्थापना गतिविधि UI स्थिति से इसे निम्नानुसार बताया गया है:

OnCreate () के दौरान राज्य को पुनर्स्थापित करने के बजाय आप onRestoreInstanceState () को लागू करना चुन सकते हैं, जिसे सिस्टम ऑनस्टार्ट () विधि के बाद कॉल करता है। सिस्टम onRestoreInstanceState () को केवल तभी कॉल करता है जब पुनर्स्थापित करने के लिए कोई सहेजा गया राज्य है, इसलिए आपको यह जांचने की आवश्यकता नहीं है कि बंडल खाली है या नहीं :

यहां छवि विवरण दर्ज करें

यहां छवि विवरण दर्ज करें

IMO, onCreate पर यह जाँचने की तुलना में अधिक स्पष्ट तरीका है, और एकल जिम्मेदारी वाले सिद्धांत के साथ बेहतर फिट बैठता है।


0

मेरे मामले में, onRestoreInstanceStateडिवाइस ओरिएंटेशन बदलने के बाद गतिविधि को फिर से संगठित किया गया था। onCreate(Bundle)पहले कहा जाता था, लेकिन बंडल में मेरे द्वारा निर्धारित कुंजी / मान नहीं थे onSaveInstanceState(Bundle)

ठीक बाद, onRestoreInstanceState(Bundle)एक बंडल के साथ बुलाया गया था जिसमें सही कुंजी / मान थे।


0

मैं बस इसमें भाग गया और यह देख रहा था कि दस्तावेज में मेरा जवाब था:

"यह फ़ंक्शन कभी भी अशक्त अवस्था में नहीं कहा जाएगा।"

https://developer.android.com/reference/android/view/View.html#onRestoreInstanceState(android.os.Parcelable)

मेरे मामले में, मैं सोच रहा था कि onRestoreInstanceState को प्रारंभिक इंस्टेंटेशन पर क्यों नहीं बुलाया जा रहा है। इसका मतलब यह भी है कि यदि आप कुछ भी स्टोर नहीं करते हैं, तो जब आप अपने दृश्य को फिर से संगठित करने के लिए जाएंगे तो इसे कॉल नहीं किया जाएगा।


0

मैं ऐसा कर सकता हूं (क्षमा करें यह c # नहीं जावा है लेकिन यह कोई समस्या नहीं है ...):

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
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.