onSaveInstanceState () এবং onRestoreInstanceState ()


138

আমি Activityপদ্ধতিগুলি onSaveInstanceState()এবং ব্যবহার করে রাষ্ট্রের সংরক্ষণ এবং পুনরুদ্ধার করার চেষ্টা করছি onRestoreInstanceState()

সমস্যাটি হ'ল এটি onRestoreInstanceState()পদ্ধতিতে প্রবেশ করে না । কেউ আমাকে বোঝাতে পারেন কেন এটি?


1
@ নিতিন: লিঙ্কটি ভাগ করে নেওয়ার জন্য ধন্যবাদ ... এটি আমার জন্য কয়েকটি জিনিস পরিষ্কার করেছে +1
টালিয়াদন

2
@ নিতিনবংশাল লিঙ্কটি মারা গেছে।
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
সমস্যাটি হ'ল আমি ক্রিয়াকলাপে ফিরে আসার জন্য স্টার্টঅ্যাক্টিভিটি ব্যবহার করি এ। ক্রিয়াকলাপ বিতে ফিরে আসার সময় অবজেক্টটি নাল আইসিক্যাল।
ব্লাবিআরআ

5
যদি আমি সঠিকভাবে বুঝতে পারি তবে আপনি যা করছেন এটিই: বি থেকে আপনি স্টার্টঅ্যাক্টিভিটি (এ) কল করেন। তারপরে এ থেকে আপনি বি শেষ করতে কল করুন ()? সেক্ষেত্রে আপনার প্রথম ক্রিয়াকলাপ, বি ধ্বংস করা হবে না এবং অনক্রিট () বা অন -স্টোরইস্ট্যান্সস্টেট ()ও বলা হবে না। এই পদ্ধতিগুলি কেবল যখন প্রয়োজন হয় তখনই ডাকা হয়, এটি তখনই যখন কোনও ক্রিয়াকলাপ ধ্বংস হয়ে যায় এবং সিস্টেম দ্বারা পুনরায় তৈরি করা দরকার।
রবার্ট

4
আমার যুক্ত করা উচিত যে আপনার প্রথম ক্রিয়াকলাপ, বি কম স্মৃতির শর্তের কারণে ধ্বংস হয়ে যেতে পারে। এটি onCreate এবং onRestoreInstanceState ট্রিগার করবে।
রবার্ট

1
এরিকবি, হ্যাঁ, ক্রিয়াকলাপ বি পুনরায় চালু করা হবে, বা ওএস এটিকে পুনরুদ্ধার করেছে, পুনরায় তৈরি করেছে এবং তারপরে পুনরায় চালু করা হয়েছে।
রবার্ট


149

onRestoreInstanceState()ওএস দ্বারা হত্যা করার পরে কার্যকলাপ পুনরায় শুরু করার সময় কেবল তাকে ডাকা হয় is এ জাতীয় পরিস্থিতি যখন ঘটে:

  • ডিভাইসের ওরিয়েন্টেশন পরিবর্তন হয় (আপনার ক্রিয়াকলাপটি ধ্বংস এবং পুনরায় তৈরি করা হয়েছে)।
  • আপনার সামনে আরও একটি ক্রিয়াকলাপ রয়েছে এবং কোনও সময়ে ওএস মেমরি মুক্ত করার জন্য আপনার ক্রিয়াকলাপটিকে হত্যা করে (উদাহরণস্বরূপ)। পরবর্তী সময় যখন আপনিRestoreInstanceState () তে আপনার কার্যকলাপ শুরু করবেন তখন কল করা হবে called

বিপরীতে: আপনি যদি নিজের কার্যকলাপে থাকেন এবং আপনি Backডিভাইসে বোতামটি হিট করেন তবে আপনার ক্রিয়াকলাপটি সমাপ্ত হবে () এড (যেমন এটিকে ডেস্কটপ অ্যাপ্লিকেশন হিসাবে প্রস্থান হিসাবে মনে করবেন) এবং পরের বার আপনি আপনার অ্যাপ্লিকেশনটি শুরু করলে এটি "টাটকা" শুরু হবে, অর্থাত্ ছাড়া সংরক্ষণের অবস্থা কারণ আপনি যখন আঘাত করবেন তখন আপনি ইচ্ছাকৃতভাবে এটিকে প্রস্থান করেছেন Back

বিভ্রান্তির অন্যান্য উত্স হ'ল যখন কোনও অ্যাপ্লিকেশন অন্য অ্যাপ্লিকেশনটির উপর ফোকাস হারায় onSaveInstanceState()তখন তাকে ডাকা হয় তবে আপনি যখন আপনার অ্যাপ্লিকেশনটিতে ফিরে যান তখন কল করা onRestoreInstanceState()যাবেনা। এটি মূল প্রশ্নে বর্ণিত কেস, অর্থাত্ যদি আপনার ক্রিয়াকলাপটি সেই সময়কালে হত্যা না করা হত যখন অন্য ক্রিয়াকলাপটি সামনে ছিল তখন তাকে onRestoreInstanceState()বলা হবে না কারণ আপনার কার্যকলাপটি বেশ "জীবিত"।

সব মিলিয়ে ডকুমেন্টেশনে যেমন বলা হয়েছে onRestoreInstanceState():

বেশিরভাগ বাস্তবায়নগুলি কেবল তাদের রাজ্য পুনরুদ্ধার করতে অনক্রিট (বান্ডিল) ব্যবহার করবে তবে প্রাথমিকভাবে সমস্ত কাজ সম্পন্ন করার পরে এখানে কিছু করা সুবিধাজনক হবে বা আপনার ডিফল্ট বাস্তবায়নটি ব্যবহার করতে হবে কিনা তা সিদ্ধান্তের জন্য সাবক্লাসগুলিকে অনুমতি দেওয়া হবে। এই পদ্ধতির ডিফল্ট বাস্তবায়নটি পূর্বে onSaveInstanceState (বান্ডিল) দ্বারা হিমায়িত করা হয়েছে এমন কোনও দর্শন অবস্থার পুনরুদ্ধার করে।

যেমনটি আমি এটি পড়েছি: onRestoreInstanceState()আপনি সাবক্লাসিং না করে ওভাররাইড করার কোনও কারণ নেই Activityএবং এটি প্রত্যাশিত যে কেউ আপনার সাবক্লাসটি সাবক্লাস করবে।


3
হ্যাঁ এটিকে সঠিক বলে মনে হচ্ছে তবে এটি সফল হয়। imo অন্য ক্রিয়াকলাপ থেকে ক্রিয়াকলাপে ফিরে যাওয়ার সময় এটিকে চালানো উচিত। আপনার প্রয়োজন যেখানে প্রচুর পরিস্থিতি আছে।
মাসি

4
@ ম্যাসি ইতিমধ্যে কার্যকলাপে অন্যান্য পদ্ধতি আহ্বান করা হয়েছে যখন ব্যবহারকারী এটিতে ফিরে আসে (অন্য ক্রিয়াকলাপ থেকে)। অন ​​সেভ / রিস্টোরআইনস্ট্যান্সস্টেট () অন্য নির্দিষ্ট উদ্দেশ্যে ব্যবহৃত হয়, এটি it
সুপারজোজ

8

আপনি যে রাষ্ট্রটি সংরক্ষণ করেছেন onSaveInstanceState()সেটি পরে onCreate()পদ্ধতি আহ্বানে পাওয়া যায় । সুতরাং আপনার ক্রিয়াকলাপের অবস্থা পুনরুদ্ধার করতে onCreate(এবং এর Bundleপরামিতি) ব্যবহার করুন ।


4

কর্মক্ষেত্র হিসাবে, আপনি ক্রিয়াকলাপ এ শুরু করার জন্য যে ইন্টেন্টটি ব্যবহার করেন তার মধ্যে আপনি যে ডেটা বজায় রাখতে চান তা দিয়ে আপনি একটি বান্ডিল সঞ্চয় করতে পারেন A.

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.

আরেকটি ধারণা হ'ল ক্রিয়াকলাপের স্টোর সংরক্ষণের জন্য একটি সংগ্রহশালা তৈরি করা এবং আপনার প্রতিটি ক্রিয়াকলাপের সেই শ্রেণিটি উল্লেখ করা (একক একটি কাঠামো ব্যবহার করা সম্ভব)) যদিও এটি করার চেয়ে এটি সম্ভবত বেশি সমস্যা trouble


3

মূল জিনিসটি আপনি যদি সংরক্ষণ না করেন onSaveInstanceState()তবে onRestoreInstanceState()ডাকা হবে না। এটি restoreInstanceState()এবং এর মধ্যে প্রধান পার্থক্য onCreate()। আপনি সত্যিই কিছু সঞ্চয় করেছেন তা নিশ্চিত করুন। সম্ভবত এটি আপনার সমস্যা।


1
#RestoreInstanceState () বলা হবে, এমনকি আপনি যদি অনসেইভইনস্টান্সস্টেটে কোনও কিছু না সঞ্চয় করেন ()
ab22ishek

3

আমি দেখতে পেলাম যে অনভিজ্ঞাস্বন্ধিকার স্টেটটি সর্বদা ডাকা হয় যখন অন্য কোনও ক্রিয়াকলাপ সম্মুখের দিকে আসে। এবং তাই অনটপ।

তবে, অনস্ট্রেইটস ইনস্ট্যান্সস্টেট কেবল তখনই কল করা হয়েছিল যখন অনক্রিট এবং অন স্টার্টকেও ডাকা হত। এবং, অনক্রিট এবং অন স্টার্ট সবসময় কল করা হয়নি।

সুতরাং দেখে মনে হচ্ছে অ্যাকডিয়াটি ব্যাকগ্রাউন্ডে সরে গেলেও অ্যান্ড্রয়েড সর্বদা রাষ্ট্রের তথ্য মুছে দেয় না। তবে, এটি কেবল নিরাপদ থাকার জন্য রাষ্ট্রকে বাঁচাতে লাইফসাইकल পদ্ধতিগুলি কল করে। সুতরাং, যদি রাজ্যটি মুছে ফেলা না হয়, তবে অ্যান্ড্রয়েড রাষ্ট্রের পুনরুদ্ধার করার জন্য জীবনচক্র পদ্ধতিগুলি কল করে না কারণ তাদের প্রয়োজন নেই।

চিত্র 2 এটি বর্ণনা করে।


2

আমি মনে করি এই থ্রেডটি বেশ পুরানো ছিল। আমি কেবল আরেকটি কেস উল্লেখ করেছি, onSaveInstanceState()এটিও বলা হবে, যখন আপনি কল করবেন Activity.moveTaskToBack(boolean nonRootActivity)


1

যদি আপনি android:configChanges="orientation|screenSize"এবং এর সাথে ক্রিয়াকলাপের ওরিয়েন্টেশন পরিবর্তনগুলি পরিচালনা করছেন onConfigurationChanged(Configuration newConfig),onRestoreInstanceState() বলা হবে না।


1

এটি দরকার নেই যে অনারস্টোরইনস্ট্যান্সস্টেট সর্বদা অন সেভ ইনস্টান্সস্টেটের পরে ডাকা হবে।

দ্রষ্টব্য: অনিয়ন্ত্রনস্ট্যান্সস্টেটটি সর্বদা ডাকা হবে, যখন ক্রিয়াকলাপটি ঘোরানো হয় (যখন ওরিয়েন্টেশন পরিচালনা করা হয় না) বা আপনার ক্রিয়াকলাপটি খুলুন এবং তারপরে অন্যান্য অ্যাপ্লিকেশনগুলি খুলুন যাতে আপনার ক্রিয়াকলাপের উদাহরণটি ওএস দ্বারা মেমরি থেকে সাফ হয়ে যায়।


1

ডকুমেন্টেশন থেকে পুনরুদ্ধার ক্রিয়াকলাপ ইউআই রাজ্য সংরক্ষণের উদাহরণ ব্যবহার করে এটি বর্ণিত হয়েছে:

অনক্রিট () এর সময় রাজ্য পুনরুদ্ধার করার পরিবর্তে আপনি onRestoreInstanceState () প্রয়োগ করতে বেছে নিতে পারেন, যা সিস্টেমটি স্টার্ট () পদ্ধতির পরে কল করে। সিস্টেমটি রিস্টোরইনস্ট্যান্স স্টেটকে কল করে কেবল তখনই যদি পুনরুদ্ধার করার জন্য কোনও সেভ স্টেট থাকে, সুতরাং আপনার বান্ডেলটি নাল কিনা তা পরীক্ষা করার দরকার নেই :

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

আইএমও, এটি অনক্রিটে পরীক্ষা করার চেয়ে আরও সুস্পষ্ট উপায় এবং একক দায়িত্ববোধ নীতিটির সাথে আরও ভাল ফিট করে।


0

আমার ক্ষেত্রে, onRestoreInstanceStateযখন ডিভাইস ওরিয়েন্টেশন পরিবর্তনের পরে ক্রিয়াকলাপটি পুনর্গঠন করা হয়েছিল তখন ডাকা হয়েছিল। onCreate(Bundle)প্রথমে বলা হয়েছিল, তবে আমার কাছে সেট করা কী / মানগুলি বান্ডলে নেই onSaveInstanceState(Bundle)

ঠিক পরে, onRestoreInstanceState(Bundle)এমন একটি বান্ডিল দিয়ে ডাকা হত যার সঠিক কী / মান ছিল।


0

আমি কেবল এটির মধ্যে দৌড়ে এসে দেখছিলাম যে ডকুমেন্টেশনের আমার উত্তর আছে:

"এই ফাংশনটি কখনই শূন্য অবস্থার সাথে ডাকা হবে না।"

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

আমার ক্ষেত্রে, আমি ভাবছিলাম কেন প্রাথমিক ইনস্ট্যান্টেশন করার জন্য কেন অনিয়ন্ত্রনস্ট্যান্স স্টেটকে ডাকা হচ্ছে না। এর অর্থ হ'ল আপনি যদি কিছু সঞ্চয় না করেন তবে আপনার দৃষ্টিভঙ্গি পুনর্গঠন করতে গেলে কল করা হবে না।


0

আমি এটি করতে পারি (দুঃখিত এটি সি # জাভা নয় তবে এটি কোনও সমস্যা নয় ...):

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
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.