सवाल सहेजें इंस्टेंस स्टेट का उपयोग करके Android गतिविधि स्थिति सहेजना


मैं एंड्रॉइड एसडीके मंच पर काम कर रहा हूं, और यह थोड़ा अस्पष्ट है कि एप्लिकेशन के राज्य को कैसे सहेजना है। इसलिए 'हैलो, एंड्रॉइड' उदाहरण के इस मामूली पुन: टूलिंग को दिया गया:

package com.android.hello;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroid extends Activity {

  private TextView mTextView = null;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mTextView = new TextView(this);

    if (savedInstanceState == null) {
       mTextView.setText("Welcome to HelloAndroid!");
    } else {
       mTextView.setText("Welcome back.");
    }

    setContentView(mTextView);
  }
}

मैंने सोचा कि यह सबसे आसान मामले के लिए पर्याप्त होगा, लेकिन यह हमेशा पहले संदेश के साथ प्रतिक्रिया करता है, इससे कोई फर्क नहीं पड़ता कि मैं ऐप से कैसे नेविगेट करता हूं।

मुझे यकीन है कि समाधान ओवरराइडिंग के रूप में सरल है onPause या ऐसा कुछ, लेकिन मैं 30 मिनट या उससे अधिक के लिए प्रलेखन में दूर जा रहा हूं और कुछ भी स्पष्ट नहीं मिला है।


2238
2017-09-30 04:41


मूल


जब सहेजा जाता हैInstanceState == शून्य और यह शून्य नहीं है? - Trojan.ZBOT
आप स्पष्ट रूप से अपनी गतिविधि को नष्ट कर रहे हैं - जैसा कि आपने कहा था, उससे दूर नेविगेट करना, जैसे कि वापस दबाकर। दरअसल, परिदृश्य जिसमें यह 'सहेजा गया इंस्टेंसस्टेट' का उपयोग किया जाता है, वह तब होता है जब एंड्रॉइड मनोरंजन के लिए आपकी गतिविधि को नष्ट कर देता है। इरादे के लिए: यदि गतिविधि चल रही थी, तो आप अपने फोन की भाषा बदलते हैं (और आपके प्रोजेक्ट से अलग संसाधनों को लोड करने की आवश्यकता है)। एक और बहुत ही आम परिदृश्य तब होता है जब आप अपने फोन को तरफ घुमाते हैं ताकि गतिविधि को फिर से बनाया जा सके और परिदृश्य में प्रदर्शित किया जा सके। - villoren
दूसरा संदेश प्राप्त करने के लिए, देव विकल्पों में "गतिविधियां न रखें" सक्षम करें। एक होम बटन दबाएं और रिकेंट से वापस आएं। - Yaroslav Mytkalyk
यह काफी उपयोगी है developer.android.com/training/basics/activity-lifecycle/... - Syed Raza Mehdi
आप इसे इसके साथ कर सकते हैं: ऑनसेवस्टेंसस्टेट (बंडल सेव किया गयास्टेंसस्टेट) - HPbyP


जवाब:


आपको ओवरराइड करने की जरूरत है onSaveInstanceState(Bundle savedInstanceState) और उस एप्लिकेशन स्टेट वैल्यू को लिखें जिसे आप बदलना चाहते हैं Bundle इस तरह पैरामीटर:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
  super.onSaveInstanceState(savedInstanceState);
  // Save UI state changes to the savedInstanceState.
  // This bundle will be passed to onCreate if the process is
  // killed and restarted.
  savedInstanceState.putBoolean("MyBoolean", true);
  savedInstanceState.putDouble("myDouble", 1.9);
  savedInstanceState.putInt("MyInt", 1);
  savedInstanceState.putString("MyString", "Welcome back to Android");
  // etc.
}

बंडल अनिवार्य रूप से एक एनवीपी ("नाम-मूल्य जोड़ी") मानचित्र को संग्रहीत करने का एक तरीका है, और इसे पास कर दिया जाएगा onCreate() और भी onRestoreInstanceState() जहां आप इस तरह के मान निकालेंगे:

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
  super.onRestoreInstanceState(savedInstanceState);
  // Restore UI state from the savedInstanceState.
  // This bundle has also been passed to onCreate.
  boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
  double myDouble = savedInstanceState.getDouble("myDouble");
  int myInt = savedInstanceState.getInt("MyInt");
  String myString = savedInstanceState.getString("MyString");
}

आप आमतौर पर इस तकनीक का उपयोग अपने आवेदन (चयन, सहेजे गए पाठ इत्यादि) के उदाहरण मानों को संग्रहीत करने के लिए करेंगे।


2275
2017-09-30 06:12



फोन पर यह कोई मौका है, लेकिन एम्यूलेटर में नहीं? मुझे एक गैर-शून्य सहेजा गया इंस्टेंसस्टेट नहीं मिल रहा है। - Adam Jack
मेरे पास इस सरणी सूची में सभी बिंदुओं को सहेजने और फिर उन्हें पुनर्स्थापित करने के लिए बिंदुओं का एक ArrayList है? - AZ_
सावधानी: बंडल में अपने मूल्य जोड़ने से पहले आपको super.onSaveInstanceState (savedInstanceState) को कॉल करने की आवश्यकता है, या वे उस कॉल (Droid X Android 2.2) पर मिटा दिए जाएंगे। - jkschneider
सावधान: आधिकारिक दस्तावेज कहता है कि आपको ऑन-ऑन-विधि के भीतर महत्वपूर्ण जानकारी को सहेजना चाहिए क्योंकि ऑनवेवइंस्टेंस-विधि एंड्रॉइड लाइफसाइक्ल का हिस्सा नहीं है। developer.android.com/reference/android/app/Activity.html - schlingel
वह तथ्य प्रभावी ढंग से बनाता है onSaveInstanceState केवल स्क्रीन अभिविन्यास परिवर्तन के मामले के अलावा लगभग बेकार। लगभग सभी अन्य मामलों में, आप इस पर भरोसा नहीं कर सकते हैं और कहीं भी अपने यूआई राज्य को मैन्युअल रूप से सहेजने की आवश्यकता होगी। या बैक बटन व्यवहार को ओवरराइड करके अपने ऐप को मारने से रोकना। मुझे समझ में नहीं आता कि उन्होंने इसे पहले स्थान पर क्यों लागू किया। पूरी तरह से अनजान। और आपके पास यह बंडल नहीं हो सकता है कि सिस्टम आपको इस विशेष विधि को छोड़कर चीजों को बचाने के लिए देता है। - chakrit


savedInstanceState केवल गतिविधि के वर्तमान उदाहरण से जुड़े राज्य को बचाने के लिए है, उदाहरण के लिए वर्तमान नेविगेशन या चयन जानकारी, ताकि अगर एंड्रॉइड किसी गतिविधि को नष्ट कर देता है और पुन: प्रयास करता है, तो यह पहले जैसा था, उतना वापस आ सकता है। के लिए प्रलेखन देखें onCreate तथा onSaveInstanceState

अधिक लंबे समय तक रहने वाले राज्य के लिए, SQLite डेटाबेस, फ़ाइल या प्राथमिकताओं का उपयोग करने पर विचार करें। देख निरंतर राज्य की बचत


375
2017-09-30 05:03



जब सहेजा जाता हैInstanceState == शून्य और यह शून्य नहीं है? - Trojan.ZBOT
सहेजा गया इंस्टेंसस्टेट शून्य है जब सिस्टम आपकी गतिविधि का एक नया उदाहरण बना रहा है और इसे पुनर्स्थापित करते समय शून्य नहीं है। - Gabriel Câmara
... जो सवाल उठाता है कब क्या सिस्टम को गतिविधि का एक नया उदाहरण बनाने की आवश्यकता है। ऐप से बाहर निकलने के कुछ तरीके बंडल नहीं बनाते हैं, इसलिए एक नया उदाहरण बनाया जाना चाहिए। यह मौलिक समस्या है; इसका मतलब है कि कोई नहीं कर सकता भरोसा करना बंडल के अस्तित्व पर, और लगातार भंडारण के कुछ वैकल्पिक साधन करना चाहिए। ऑनसेव / ऑनरस्टोर इंस्टेंसस्टेट का लाभ यह है कि यह एक तंत्र है जो सिस्टम कर सकता है एकाएक, अधिक सिस्टम संसाधनों का उपभोग किए बिना। इसलिए इसका समर्थन करना अच्छा होता है, साथ ही ऐप से अधिक सुंदर निकास के लिए लगातार भंडारण होता है। - ToolmakerSteve


ध्यान दें कि यह है नहीं उपयोग करने के लिए सुरक्षित onSaveInstanceState तथा onRestoreInstanceState  लगातार डेटा के लिए, गतिविधि राज्यों पर प्रलेखन के अनुसार http://developer.android.com/reference/android/app/Activity.html

दस्तावेज़ बताता है ('गतिविधि लाइफसाइक्ल' अनुभाग में):

ध्यान दें कि इसे सहेजना महत्वपूर्ण है   लगातार डेटा में onPause() बजाय   का onSaveInstanceState(Bundle)   क्योंकि बाद में इसका हिस्सा नहीं है   जीवन चक्र कॉलबैक, ऐसा नहीं होगा   वर्णित हर स्थिति में बुलाया   इसके दस्तावेज में।

दूसरे शब्दों में, लगातार डेटा के लिए अपना सेव / पुनर्स्थापित कोड डालें onPause() तथा onResume()!

संपादित करें: आगे स्पष्टीकरण के लिए, यहां है onSaveInstanceState() प्रलेखन:

एक गतिविधि को मारने से पहले इस विधि को बुलाया जाता है ताकि जब यह हो   भविष्य में कुछ समय वापस आ गया है यह अपने राज्य को बहाल कर सकता है। के लिये   उदाहरण के लिए, यदि गतिविधि बी गतिविधि ए के सामने और कुछ पर लॉन्च किया गया है   बिंदु गतिविधि ए संसाधनों को पुनः प्राप्त करने के लिए मारा जाता है, गतिविधि ए होगा   इसके माध्यम से अपने यूजर इंटरफेस की वर्तमान स्थिति को बचाने का मौका   विधि ताकि जब उपयोगकर्ता गतिविधि ए, राज्य की स्थिति में वापस आ जाए   यूजर इंटरफेस के माध्यम से बहाल किया जा सकता है onCreate(Bundle) या    onRestoreInstanceState(Bundle)


366
2018-05-25 23:22



बस नाइटपिक करने के लिए: यह असुरक्षित नहीं है। यह सिर्फ उस चीज़ पर निर्भर करता है जिसे आप संरक्षित करना चाहते हैं और कितनी देर तक, @ बर्नार्ड अपने मूल प्रश्न में पूरी तरह स्पष्ट नहीं है। InstanceState वर्तमान UI स्थिति (नियंत्रण में दर्ज डेटा, सूचियों में वर्तमान स्थिति और आगे) को संरक्षित करने के लिए एकदम सही है, जबकि रोक / फिर से शुरू करना दीर्घकालिक निरंतर भंडारण के लिए एकमात्र संभावना है। - Pontus Gagge
इसे कम किया जाना चाहिए। लाइफसाइकिल विधियों जैसे इंस्टेंसस्टेट (सहेजें | पुनर्स्थापित करें) पर उपयोग करना सुरक्षित नहीं है (यानी राज्य को बचाने / पुनर्स्थापित करने के अलावा उनमें कुछ और करें)। वे राज्य को बचाने / बहाल करने के लिए पूरी तरह से अच्छे हैं। साथ ही, आप स्थिति को चालू और पुनर्स्थापित कैसे करना चाहते हैं? आपको उन विधियों में बंडल नहीं मिलते हैं जिनका आप उपयोग कर सकते हैं, इसलिए आपको कुछ अन्य राज्य-बचत, डेटाबेस, फाइल आदि में नियोजित करना होगा जो बेवकूफ है। - Felix
हमें इस व्यक्ति को वोट देना नहीं चाहिए कम से कम उसने दस्तावेज़ीकरण के माध्यम से जाने के प्रयास किए हैं और मुझे लगता है कि हम वास्तव में एक जानकार समुदाय बनाने के लिए यहां हैं और एक दूसरे को वोट कम करने में मदद नहीं करते हैं। इसलिए 1 प्रयास के लिए वोट दें और मैं आपसे अनुरोध करता हूं कि वोट न दें, मतदान न करें या वोट न दें .... यह व्यक्ति भ्रम को साफ़ करता है कि दस्तावेज के माध्यम से जाने पर कोई भी ऐसा करना चाहता है। 1 वोट अप :) - AZ_
मुझे नहीं लगता कि यह जवाब एक डाउनवोट का हकदार है। कम से कम उन्होंने जवाब देने का प्रयास किया और डॉको से एक खंड उद्धृत किया था। - GSree
यह जवाब बिल्कुल सही है और यूपी वोट का हकदार है, नीचे नहीं! मुझे उन लोगों के लिए राज्यों के बीच अंतर स्पष्ट करने दें जो इसे नहीं देखते हैं। एक जीयूआई राज्य, जैसे चयनित रेडियो-बटन और इनपुट फ़ील्ड में कुछ टेक्स्ट, डेटा स्थिति से बहुत कम महत्वपूर्ण है, जैसे ListView में प्रदर्शित सूची में जोड़े गए रिकॉर्ड। बाद वाले को डेटाबेस में डेटाबेस में संग्रहीत किया जाना चाहिए क्योंकि यह केवल गारंटीकृत कॉल है। यदि आप इसे इसके बजाय SaveInstanceState में डालते हैं, तो आपको डेटा खोने का जोखिम होता है यदि उसे नहीं कहा जाता है। लेकिन यदि रेडियो-बटन चयन उसी कारण से सहेजा नहीं जाता है - यह एक बड़ा सौदा नहीं है। - JBM


मेरे सहयोगी ने एंड्रॉइड उपकरणों पर एप्लिकेशन स्टेट को समझाते हुए एक लेख लिखा जिसमें गतिविधि लाइफसाइक्ल और राज्य सूचना, राज्य जानकारी कैसे स्टोर करें और राज्य को सहेजना शामिल है Bundle तथा SharedPreferences तथा यहां एक नज़र डालें

लेख में तीन दृष्टिकोण शामिल हैं:

इंस्टेंस स्टेट बंडल का उपयोग करके एप्लिकेशन जीवनकाल (यानी अस्थायी रूप से) के लिए स्थानीय वैरिएबल / यूआई नियंत्रण डेटा स्टोर करें

[Code sample – Store State in State Bundle]
@Override
public void onSaveInstanceState(Bundle savedInstanceState) 
{
  // Store UI state to the savedInstanceState.
  // This bundle will be passed to onCreate on next call.  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  savedInstanceState.putString(“Name”, strName);
  savedInstanceState.putString(“Email”, strEmail);
  savedInstanceState.putBoolean(“TandC”, blnTandC);

  super.onSaveInstanceState(savedInstanceState);
}

साझा प्राथमिकताओं का उपयोग कर अनुप्रयोग उदाहरणों (यानी स्थायी रूप से) के बीच स्थानीय वैरिएबल / यूआई नियंत्रण डेटा स्टोर करें

[Code sample – Store State in SharedPreferences]
@Override
protected void onPause() 
{
  super.onPause();

  // Store values between instances here
  SharedPreferences preferences = getPreferences(MODE_PRIVATE);
  SharedPreferences.Editor editor = preferences.edit();  // Put the values from the UI
  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  editor.putString(“Name”, strName); // value to store
  editor.putString(“Email”, strEmail); // value to store
  editor.putBoolean(“TandC”, blnTandC); // value to store    
  // Commit to storage
  editor.commit();
}

बनाए गए गैर-कॉन्फ़िगरेशन इंस्टेंस का उपयोग करके एप्लिकेशन जीवनकाल में गतिविधियों के बीच स्मृति में ऑब्जेक्ट उदाहरणों को जीवित रखना

[Code sample – store object instance]
private cMyClassType moInstanceOfAClass;// Store the instance of an object
@Override
public Object onRetainNonConfigurationInstance() 
{
  if (moInstanceOfAClass != null) // Check that the object exists
      return(moInstanceOfAClass);
  return super.onRetainNonConfigurationInstance();
}

171
2017-08-27 13:54



@ मार्टिनबेल्चर-ईगो आलेख SharePreferences में डेटा के बारे में बताता है कि "यह डेटा डिवाइस पर डेटाबेस में लिखा गया है .." मुझे विश्वास है कि फ़ाइल फ़ाइल सिस्टम की ऐप की निर्देशिका में फ़ाइल में संग्रहीत है। - Tom
@Tom SharefPrefs डेटा xml फ़ाइल में लिखा गया है। क्या XML एक प्रकार का डेटाबेस है? मैं कहूंगा कि यह है;) - MaciejGórski
ध्यान दें कि editor.apply() से तेज है editor.commit()। - Fred
लिंक मर चुका है। - Sakiboy


यह एंड्रॉइड विकास का क्लासिक 'गॉचा' है। यहां दो समस्याएं हैं:

  • एक सूक्ष्म एंड्रॉइड फ्रेमवर्क बग है जो कम से कम विरासत संस्करणों पर विकास के दौरान एप्लिकेशन स्टैक प्रबंधन को बहुत जटिल बनाता है (पूरी तरह से सुनिश्चित नहीं है कि / कब / कब तय किया गया था)। मैं नीचे इस बग पर चर्चा करूंगा।
  • इस मुद्दे को प्रबंधित करने के लिए 'सामान्य' या इच्छित तरीका है, बजाय, ऑन / ऑन रीज़्यूम और ऑनसेवेंसस्टेट / ऑनस्टोर इंस्टेंसस्टेट की द्वंद्व के साथ जटिल है

इन सभी धागे में ब्राउज़िंग, मुझे संदेह है कि ज्यादातर समय डेवलपर्स इन दो अलग-अलग मुद्दों के बारे में बात कर रहे हैं ... इसलिए सभी भ्रम और रिपोर्ट "यह मेरे लिए काम नहीं करती है"।

सबसे पहले, 'इच्छित' व्यवहार को स्पष्ट करने के लिए: ऑनसेवेंस और ऑनस्टोर इंस्टेंस नाजुक हैं और केवल क्षणिक स्थिति के लिए हैं। इच्छित उपयोग (afaict) फोन घुमाए जाने पर गतिविधि मनोरंजन को संभालना है (अभिविन्यास परिवर्तन)। दूसरे शब्दों में, इच्छित उपयोग तब होता है जब आपकी गतिविधि अभी भी 'शीर्ष पर' तर्कसंगत है, लेकिन फिर भी सिस्टम द्वारा इसे पुनर्स्थापित किया जाना चाहिए। सहेजे गए बंडल को प्रक्रिया / मेमोरी / जीसी के बाहर नहीं रखा जाता है, इसलिए यदि आप पृष्ठभूमि में जाते हैं तो आप वास्तव में इस पर भरोसा नहीं कर सकते हैं। हां, शायद आपकी गतिविधि की याददाश्त पृष्ठभूमि की अपनी यात्रा से बच जाएगी और जीसी से बच जाएगी, लेकिन यह विश्वसनीय नहीं है (न ही यह अनुमानित है)।

तो यदि आपके पास ऐसा परिदृश्य है जहां सार्थक 'उपयोगकर्ता प्रगति' या राज्य है जो आपके आवेदन के 'लॉन्च' के बीच जारी रहना चाहिए, तो मार्गदर्शन और कारण पर उपयोग करना है। आपको खुद को एक सतत स्टोर चुनना और तैयार करना होगा।

लेकिन - एक बहुत भ्रमित बग है जो इस सब को जटिल बनाता है। विवरण यहां हैं:

http://code.google.com/p/android/issues/detail?id=2373

http://code.google.com/p/android/issues/detail?id=5277

असल में, यदि आपका एप्लिकेशन सिंगलटास्क ध्वज के साथ लॉन्च किया गया है, और उसके बाद आप इसे होम स्क्रीन या लॉन्चर मेनू से लॉन्च करते हैं, तो उसके बाद के आमंत्रण से एक नया कार्य तैयार होगा ... आपके प्रभावी ढंग से आपके ऐप के दो अलग-अलग उदाहरण होंगे एक ही ढेर में रहना ... जो बहुत अजीब हो जाता है। ऐसा तब होता है जब आप विकास के दौरान अपना ऐप लॉन्च करते हैं (यानी एक्लिप्स या इंटेलिज से), इसलिए डेवलपर्स इसमें बहुत कुछ चलाते हैं। लेकिन कुछ ऐप स्टोर अपडेट मैकेनिज्म के माध्यम से भी (इसलिए यह आपके उपयोगकर्ताओं को भी प्रभावित करता है)।

मैंने इन थ्रेडों के माध्यम से घंटों तक लड़ाई लड़ी थी इससे पहले कि मुझे एहसास हुआ कि मेरा मुख्य मुद्दा यह बग था, इरादा ढांचा व्यवहार नहीं। एक महान लेखन और वैकल्पिक हल (अद्यतन: नीचे देखें) इस उत्तर में उपयोगकर्ता @kaciula से प्रतीत होता है:

होम कुंजी प्रेस व्यवहार

अद्यतन जून 2013: महीनों बाद, मुझे अंत में 'सही' समाधान मिला है। आपको किसी भी राज्य के शुरूआती ऐप को स्वयं प्रबंधित करने की आवश्यकता नहीं है, आप इसे ढांचे से और उचित रूप से जमानत से पहचान सकते हैं। मैं इसे अपने LauncherActivity.onCreate की शुरुआत के करीब उपयोग करता हूं:

if (!isTaskRoot()) {
    Intent intent = getIntent();
    String action = intent.getAction();
    if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && action != null && action.equals(Intent.ACTION_MAIN)) {
        finish();
        return;
    }
}

126
2017-10-19 23:47



Android फिर से दूसरी पसंद मोबाइल ओएस क्यों बन गया? हाथों में सिर उड़ाता है - Nick Bauer


onSaveInstanceStateसिस्टम को स्मृति की आवश्यकता होती है और एप्लिकेशन को मारने पर बुलाया जाता है। यह तब नहीं कहा जाता जब उपयोगकर्ता सिर्फ एप्लिकेशन को बंद कर देता है। तो मुझे लगता है कि आवेदन स्थिति भी सहेजा जाना चाहिए onPause इसे कुछ लगातार भंडारण में सहेजा जाना चाहिए Preferences या Sqlite


70
2018-05-07 00:21



क्षमा करें, यह बिल्कुल सही नहीं है। गतिविधि को फिर से बनाने की आवश्यकता होने से पहले SaveInstanceState को बुलाया जाता है। यानी हर बार उपयोगकर्ता डिवाइस को घुमाता है। यह क्षणिक दृश्य राज्यों को संग्रहित करने के लिए है। जब एंड्रॉइड एप्लिकेशन को बंद करने के लिए मजबूर करता है, तो SaveInstanceState को वास्तव में नहीं कहा जाता है (यही कारण है कि यह महत्वपूर्ण एप्लिकेशन डेटा संग्रहीत करने के लिए असुरक्षित है)। पर रोकें, हालांकि गतिविधि की मौत से पहले बुलाया जाने की गारंटी है, इसलिए इसका उपयोग वरीयताओं या स्कुलाइट में स्थायी जानकारी को स्टोर करने के लिए किया जाना चाहिए। सही जवाब, गलत कारण। - moveaway00
@ moveaway00 - आंशिक रूप से गलत। यदि सिस्टम संसाधनों को पुनर्प्राप्त करने के लिए ऐप को मारता है, तो यह कर देता है SaveInstanceState पर कॉल करें। से developer.android.com/training/basics/activity-lifecycle/... - "सिस्टम आपकी गतिविधि को भी नष्ट कर सकता है ... अग्रभूमि गतिविधि को अधिक संसाधनों की आवश्यकता होती है ताकि सिस्टम को स्मृति पुनर्प्राप्ति के लिए पृष्ठभूमि प्रक्रियाओं को बंद कर दिया जाए। ... यदि सिस्टम गतिविधि को नष्ट कर देता है सिस्टम की बाधाएं ... सिस्टम याद करता है कि यह अस्तित्व में है ... सहेजा गया डेटा ... एक बंडल ऑब्जेक्ट में संग्रहीत कुंजी-मूल्य जोड़े का संग्रह है। " - ToolmakerSteve


दोनों विधियां उपयोगी और वैध हैं और दोनों अलग-अलग परिदृश्यों के लिए सबसे उपयुक्त हैं:

  1. उपयोगकर्ता एप्लिकेशन को समाप्त कर देता है और इसे बाद की तारीख में फिर से खोलता है, लेकिन एप्लिकेशन को अंतिम सत्र से डेटा पुनः लोड करने की आवश्यकता होती है - इसके लिए SQLite का उपयोग करने जैसे लगातार संग्रहण दृष्टिकोण की आवश्यकता होती है।
  2. उपयोगकर्ता एप्लिकेशन को स्विच करता है और फिर मूल पर वापस आ जाता है और जहां वह छोड़ा जाता है उसे चुनना चाहता है - बंडल डेटा को सहेजना और पुनर्स्थापित करना (जैसे एप्लिकेशन स्टेट डेटा) onSaveInstanceState() तथा onRestoreInstanceState() आमतौर पर पर्याप्त है।

यदि आप राज्य डेटा को लगातार तरीके से सहेजते हैं, तो इसे एक में पुनः लोड किया जा सकता है onResume() या onCreate() (या वास्तव में किसी भी जीवन चक्र कॉल पर)। यह वांछित व्यवहार हो सकता है या नहीं भी हो सकता है। यदि आप इसे एक बंडल में स्टोर करते हैं InstanceState, तो यह क्षणिक है और केवल उसी उपयोगकर्ता के सत्र में उपयोग के लिए डेटा संग्रहीत करने के लिए उपयुक्त है (मैं शब्द सत्र को कम से कम उपयोग करता हूं) लेकिन 'सत्र' के बीच नहीं।

ऐसा नहीं है कि एक दृष्टिकोण दूसरे की तुलना में बेहतर है, सबकुछ की तरह, यह समझना महत्वपूर्ण है कि आपको किस व्यवहार की आवश्यकता है और सबसे उपयुक्त दृष्टिकोण चुनना है।


59
2018-06-27 16:17



निरंतर भंडारण की तलाश करते समय हम SQLite और प्राथमिकताओं के बीच कैसे चयन करते हैं? - Deco


जहां तक ​​मेरा संबंध है, राज्य को सहेजना सबसे अच्छा है। यदि आपको लगातार डेटा को सहेजने की आवश्यकता है, तो बस एक का उपयोग करें SQLite डेटाबेस। एंड्रॉइड इसे बनाता है SOOO आसान।

कुछ इस तरह:

import java.util.Date;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class dataHelper {

    private static final String DATABASE_NAME = "autoMate.db";
    private static final int DATABASE_VERSION = 1;

    private Context context;
    private SQLiteDatabase db;
    private OpenHelper oh ;

    public dataHelper(Context context) {
        this.context = context;
        this.oh = new OpenHelper(this.context);
        this.db = oh.getWritableDatabase();
    }

    public void close()
    {
        db.close();
        oh.close();
        db = null;
        oh = null;
        SQLiteDatabase.releaseMemory();
    }


    public void setCode(String codeName, Object codeValue, String codeDataType)
    {
        Cursor codeRow = db.rawQuery("SELECT * FROM code WHERE codeName = '"+  codeName + "'", null);
        String cv = "" ;

        if (codeDataType.toLowerCase().trim().equals("long") == true)
        {
            cv = String.valueOf(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("int") == true)
        {
            cv = String.valueOf(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("date") == true)
        {
            cv = String.valueOf(((Date)codeValue).getTime());
        }
        else if (codeDataType.toLowerCase().trim().equals("boolean") == true)
        {
            String.valueOf(codeValue);
        }
        else
        {
            cv = String.valueOf(codeValue);
        }

        if(codeRow.getCount() > 0) //exists-- update
        {
            db.execSQL("update code set codeValue = '" + cv +
                "' where codeName = '" + codeName + "'");
        }
        else // does not exist, insert
        {
            db.execSQL("INSERT INTO code (codeName, codeValue, codeDataType) VALUES(" +
                    "'" + codeName + "'," +
                    "'" + cv + "'," +
                    "'" + codeDataType + "')" );
        }
    }

    public Object getCode(String codeName, Object defaultValue)
    {
        //Check to see if it already exists
        String codeValue = "";
        String codeDataType = "";
        boolean found = false;
        Cursor codeRow  = db.rawQuery("SELECT * FROM code WHERE codeName = '"+  codeName + "'", null);
        if (codeRow.moveToFirst())
        {
            codeValue = codeRow.getString(codeRow.getColumnIndex("codeValue"));
            codeDataType = codeRow.getString(codeRow.getColumnIndex("codeDataType"));
            found = true;
        }

        if (found == false)
        {
            return defaultValue;
        }
        else if (codeDataType.toLowerCase().trim().equals("long") == true)
        {
            if (codeValue.equals("") == true)
            {
                return (long)0;
            }
            return Long.parseLong(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("int") == true)
        {
            if (codeValue.equals("") == true)
            {
                return (int)0;
            }
            return Integer.parseInt(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("date") == true)
        {
            if (codeValue.equals("") == true)
            {
                return null;
            }
            return new Date(Long.parseLong(codeValue));
        }
        else if (codeDataType.toLowerCase().trim().equals("boolean") == true)
        {
            if (codeValue.equals("") == true)
            {
                return false;
            }
            return Boolean.parseBoolean(codeValue);
        }
        else
        {
            return (String)codeValue;
        }
    }


    private static class OpenHelper extends SQLiteOpenHelper {

        OpenHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("CREATE TABLE IF  NOT EXISTS code" +
            "(id INTEGER PRIMARY KEY, codeName TEXT, codeValue TEXT, codeDataType TEXT)");
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }
    }
}

उसके बाद एक साधारण कॉल

dataHelper dh = new dataHelper(getBaseContext());
String status = (String) dh.getCode("appState", "safetyDisabled");
Date serviceStart = (Date) dh.getCode("serviceStartTime", null);
dh.close();
dh = null;

50
2018-06-23 17:07



क्योंकि SQLite डेटाबेस लोड करने में बहुत लंबा समय लगता है, यह देखते हुए कि यह उपयोगकर्ता को ऐप के UI को दिखाने के महत्वपूर्ण पथ पर है। मैंने वास्तव में इसका समय नहीं लगाया है, इसलिए मुझे सही होने में खुशी है, लेकिन निश्चित रूप से डेटाबेस फ़ाइल लोड करना और खोलना तेज नहीं होगा? - Tom
एक समाधान प्रदान करने के लिए बहुत बहुत धन्यवाद, एक नौसिखिया अपने ऐप में कट और पेस्ट कर सकता है और तुरंत उपयोग कर सकता है! @ टॉम जहां तक ​​गति होती है, 1000 जोड़े को स्टोर करने में लगभग सात सेकंड लगते हैं, लेकिन आप इसे AsyncTask में कर सकते हैं। हालांकि, आपको अंततः {cursor.close ()} जोड़ने की आवश्यकता है या यह करने के दौरान यह स्मृति रिसाव से क्रैश हो जाएगा। - Noumenon
मैं इस पर आया और जब यह साफ दिखता है तो मैं Google ग्लास पर इसका उपयोग करने का प्रयास करने में संकोच करता हूं, जो डिवाइस मैं हाल ही में / साथ काम कर रहा हूं। - Stephen Tetreault