2012-12-01 18 views
23

मैं अपने एंड्रॉइड गेम के सभी डेटा को सहेजे गए इन्स्टेंसस्टेट बंडल में फिट करने के लिए बहुत अधिक समय तक चला गया हूं। कई पार्सेलबल ऑब्जेक्ट्स सहित, बहुत सारे डेटा पूरी तरह से हैं। इससे यह सुनिश्चित होता है कि जब ऐप रोका जाता है या अभिविन्यास बदलता है, तो गतिविधि को पुन: निर्मित होने से कोई डेटा खो जाता है।बंडल को साझा किए गए संदर्भों में सहेजें

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

2 समाधान अब तक के बारे में सुना है:

1) उन्मुखीकरण परिवर्तन के लिए savedInstanceState बंडल का उपयोग करें, लेकिन यह भी है कि एप्लिकेशन को पूरी तरह से बंद किए जाने की आवश्यकता के लिए SharedPrefs शामिल करते हैं।

यह अविश्वसनीय रूप से काउंटर-उत्पादक लगता है, क्योंकि यह मूल रूप से वही काम करने के लिए 2 अलग-अलग तरीकों का उपयोग करता है। साथ ही, चूंकि मेरे सहेजे गए इंस्टेंसस्टेट बंडल पार्ससेल योग्य ऑब्जेक्ट्स का उपयोग करता है, इसलिए मुझे उन सभी ऑब्जेक्ट्स को एक और तरीका देना होगा ताकि उन्हें SharePrefs पर लिखा जा सके। अनिवार्य रूप से डुप्लिकेट और हार्ड-टू-प्रबंधित कोड के बहुत सारे।

2) सहेजे गए इंस्टेंसस्टेट बंडल को क्रमबद्ध करें और इसे सीधे फ़ाइल में लिखें।

मैं इसके लिए खुला हूं, लेकिन मुझे वास्तव में यह नहीं पता कि इसे करने के बारे में कैसे जाना है। हालांकि, मैं अभी भी उम्मीद कर रहा हूं कि एक बेहतर समाधान हो सकता है, जैसा कि मैंने सुना है कि एंड्रॉइड में क्रमबद्धता "हास्यपूर्ण/असामान्य रूप से धीमी" है।

अगर कोई मुझे इसका समाधान प्रदान कर सकता है तो मैं बहुत आभारी रहूंगा।

+0

क्रमबद्ध करने के लिए केवल एक क्रमबद्धता वर्ग की तलाश करें, इसे ढूंढना बहुत कठिन नहीं होना चाहिए। मैंने – mango

+0

का उपयोग करते समय किसी भी परेशानी में देरी नहीं देखी है मुझे केवल एक ही जानकारी मिलती है जो मुझे बताती है कि मुझे सीरियलज़ेबल को लागू करने की आवश्यकता है - लेकिन बंडल इस इंटरफ़ेस को लागू नहीं करता है। – Dan

+0

मैं पुस्तकालय https://github.com/iamironz/binaryprefs की अनुशंसा करता हूं, यह कार्यान्वयन के माध्यम से मानक जावा जैसे डेटा को सहेजने की अनुमति देता है स्थायी इंटरफ़ेस (जेडीके में बाहरी इंटरफ़ेस) –

उत्तर

3

अब मैं इस समस्या के अपने स्वयं के समाधान के साथ आया हूं, जो साझा किए गए संदर्भों में बंडलों को सहेजने का अर्द्ध स्वचालित माध्यम है। मैं अर्द्ध स्वचालित कहता हूं, हालांकि बंडल को सहेजने के लिए केवल एक विधि की आवश्यकता होती है, फिर से डेटा पुनर्प्राप्त करना और इसे वापस बंडल में बदलना कुछ काम करता है।

यहाँ बंडल को बचाने के लिए कोड है:

SharedPreferences save = getSharedPreferences(SAVE, MODE_PRIVATE); 
Editor ed = save.edit(); 
saveBundle(ed, "", gameState); 

/** 
* Manually save a Bundle object to SharedPreferences. 
* @param ed 
* @param header 
* @param gameState 
*/ 
private void saveBundle(Editor ed, String header, Bundle gameState) { 
    Set<String> keySet = gameState.keySet(); 
    Iterator<String> it = keySet.iterator(); 

    while (it.hasNext()){ 
     key = it.next(); 
     o = gameState.get(key); 
     if (o == null){ 
      ed.remove(header + key); 
     } else if (o instanceof Integer){ 
      ed.putInt(header + key, (Integer) o); 
     } else if (o instanceof Long){ 
      ed.putLong(header + key, (Long) o); 
     } else if (o instanceof Boolean){ 
      ed.putBoolean(header + key, (Boolean) o); 
     } else if (o instanceof CharSequence){ 
      ed.putString(header + key, ((CharSequence) o).toString()); 
     } else if (o instanceof Bundle){ 
      saveBundle(header + key, ((Bundle) o)); 
     } 
    } 

    ed.commit(); 
} 

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

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

मैंने तब अपने सभी पूर्व-पार्सेलबल ऑब्जेक्ट्स में रचनाकारों को लिखा ताकि वे साझा किए गए डेटा संग्रहीत डेटा से खुद को फिर से बंडल कर सकें। आपको आवश्यक डेटा के लिए कुंजी को पुनर्निर्माण करना काफी आसान है।

Bundle b { 
    KEY_X -> int x; 
    KEY_Y -> Bundle y { 
       KEY_Z -> int z; 
      } 
} 

ये SharedPreferences में सहेजा जाएगा इस प्रकार है:: आप निम्न डेटा संरचना है कहो

KEY_X -> x 
KEY_YKEY_Z -> z 

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

+0

हम इस स्थिति में कैसे बंडल प्राप्त कर सकते हैं? धन्यवाद –

+1

मुझे यकीन नहीं है कि आपका क्या मतलब है ... एक बार बंडल को SharePrefs में सहेजा गया है, इसे किसी भी अन्य बंडल की तरह पुनर्प्राप्त किया जा सकता है। – Dan

+0

कुंजी और ओ यहाँ क्या हैं। फॉर्म जहां आप इन बहसों को पास करते हैं – ekjyot

18

मजेदार, इस सप्ताह, Android Weekly के मुद्दे 47 ने इस लाइब्रेरी को छोड़ा: android complex preferences

यह आपके लिए उपयुक्त होना चाहिए।

+0

यह इतना आशाजनक लग रहा था, लेकिन हां, मैं इसे काम नहीं कर सकता कुछ भी। मैंने खाली बंडल सहित विभिन्न बंडल ऑब्जेक्ट्स और पॉइंट्स जैसी कुछ सरल वस्तुओं के साथ प्रयास किया है, लेकिन अभी भी कोई भाग्य नहीं है। यह या तो सहेजते समय "परिपत्र संदर्भ" के बारे में शिकायत करता है, या लोड होने पर "कुंजी ___ पर संग्रहीत ऑब्जेक्ट एक अन्य गेम का उदाहरण है"। यह मुझे पागल कर रहा है ... – Dan

+0

कृपया इसे एक अलग प्रश्न के रूप में पोस्ट करें। यदि आप मेरे पते पर कोई टिप्पणी जोड़ते हैं तो मुझे दिलचस्पी होगी ताकि मैं इसका अनुसरण कर सकूं। – Snicolas

+1

वास्तव में यह जीएसओएन का उपयोग कर जेएसओएन के रूप में सबकुछ बचा रहा है ... किसी भी तरह, मेरी भावना यह है कि आपका डेटा कुछ के आंतरिक वर्ग हो सकता है। यह आपको चक्रों को बहुत आसानी से देगा। क्या आपके पीओजेओ अलग वर्ग हैं? – Snicolas

1

मैंने डैन से उत्तर को बंडलों को स्वचालित रूप से फिर से बनाने के लिए उत्तर दिया, और नामों को संघर्ष करने की संभावना कम हो गई।

private static final String SAVED_PREFS_BUNDLE_KEY_SEPARATOR = "§§"; 

/** 
* Save a Bundle object to SharedPreferences. 
* 
* NOTE: The editor must be writable, and this function does not commit. 
* 
* @param editor SharedPreferences Editor 
* @param key SharedPreferences key under which to store the bundle data. Note this key must 
*   not contain '§§' as it's used as a delimiter 
* @param preferences Bundled preferences 
*/ 
public static void savePreferencesBundle(SharedPreferences.Editor editor, String key, Bundle preferences) { 
    Set<String> keySet = preferences.keySet(); 
    Iterator<String> it = keySet.iterator(); 
    String prefKeyPrefix = key + SAVED_PREFS_BUNDLE_KEY_SEPARATOR; 

    while (it.hasNext()){ 
     String bundleKey = it.next(); 
     Object o = preferences.get(bundleKey); 
     if (o == null){ 
      editor.remove(prefKeyPrefix + bundleKey); 
     } else if (o instanceof Integer){ 
      editor.putInt(prefKeyPrefix + bundleKey, (Integer) o); 
     } else if (o instanceof Long){ 
      editor.putLong(prefKeyPrefix + bundleKey, (Long) o); 
     } else if (o instanceof Boolean){ 
      editor.putBoolean(prefKeyPrefix + bundleKey, (Boolean) o); 
     } else if (o instanceof CharSequence){ 
      editor.putString(prefKeyPrefix + bundleKey, ((CharSequence) o).toString()); 
     } else if (o instanceof Bundle){ 
      savePreferencesBundle(editor, prefKeyPrefix + bundleKey, ((Bundle) o)); 
     } 
    } 
} 

/** 
* Load a Bundle object from SharedPreferences. 
* (that was previously stored using savePreferencesBundle()) 
* 
* NOTE: The editor must be writable, and this function does not commit. 
* 
* @param sharedPreferences SharedPreferences 
* @param key SharedPreferences key under which to store the bundle data. Note this key must 
*   not contain '§§' as it's used as a delimiter 
* 
* @return bundle loaded from SharedPreferences 
*/ 
public static Bundle loadPreferencesBundle(SharedPreferences sharedPreferences, String key) { 
    Bundle bundle = new Bundle(); 
    Map<String, ?> all = sharedPreferences.getAll(); 
    Iterator<String> it = all.keySet().iterator(); 
    String prefKeyPrefix = key + SAVED_PREFS_BUNDLE_KEY_SEPARATOR; 
    Set<String> subBundleKeys = new HashSet<String>(); 

    while (it.hasNext()) { 

     String prefKey = it.next(); 

     if (prefKey.startsWith(prefKeyPrefix)) { 
      String bundleKey = StringUtils.removeStart(prefKey, prefKeyPrefix); 

      if (!bundleKey.contains(SAVED_PREFS_BUNDLE_KEY_SEPARATOR)) { 

       Object o = all.get(prefKey); 
       if (o == null) { 
        // Ignore null keys 
       } else if (o instanceof Integer) { 
        bundle.putInt(bundleKey, (Integer) o); 
       } else if (o instanceof Long) { 
        bundle.putLong(bundleKey, (Long) o); 
       } else if (o instanceof Boolean) { 
        bundle.putBoolean(bundleKey, (Boolean) o); 
       } else if (o instanceof CharSequence) { 
        bundle.putString(bundleKey, ((CharSequence) o).toString()); 
       } 
      } 
      else { 
       // Key is for a sub bundle 
       String subBundleKey = StringUtils.substringBefore(bundleKey, SAVED_PREFS_BUNDLE_KEY_SEPARATOR); 
       subBundleKeys.add(subBundleKey); 
      } 
     } 
     else { 
      // Key is not related to this bundle. 
     } 
    } 

    // Recursively process the sub-bundles 
    for (String subBundleKey : subBundleKeys) { 
     Bundle subBundle = loadPreferencesBundle(sharedPreferences, prefKeyPrefix + subBundleKey); 
     bundle.putBundle(subBundleKey, subBundle); 
    } 


    return bundle; 
} 
+0

https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/src-html/org/ apache/commons/lang/StringUtils.html क्या स्ट्रिंग उपयोग करता है funcs कर रहे हैं (एंड्रॉइड में शामिल नहीं है) –

संबंधित मुद्दे