2011-07-29 20 views
8

मुझे लगता है कि यह पूछा जाता है और पहले पूछा जाता है, लेकिन फिर भी, ऐसी चीजें हैं जिन्हें मैं समझ नहीं पा रहा हूं।एंड्रॉइड छवि कैशिंग - कैसे?

मैं दो अलग-अलग दृष्टिकोण की कोशिश की है:

  1. स्मृति, में सभी छवियों, एंड्रॉयड ठीक इस SoftReferences साथ जब निश्चित सीमा से अधिक करने के लिए शुरू कर दिया है रखें उन्हें हटाने
  2. शुरू करते हैं

2 में। यह सिर्फ उन्हें साफ कर रहा है कभी-कभी दूसरा मैं उन्हें आवंटित करता हूं! और मैं बहुत ज्यादा आवंटित नहीं करता - 30-40 छवियां 50x50 पिक्सेल।

तो मैं एक से चिपक रहा हूं। सवाल यह है कि सीमा क्या है?

  1. क्या मुझे डिवाइस से कुछ विश्वसनीय जानकारी मिल सकती है कि मैंने कितनी बिटमैप मेमोरी छोड़ी है? मैंने कुछ शोध किया है, डीडीएमएस मूल्यों को देखते हैं, यह विस्फोट होने तक अधिक से अधिक जगह ले रहा है (यदि मैं साफ़ नहीं करता)। एक पल केवल 200K शेष है, अगला सिस्टम 2 एम और अधिक प्रदान करता है ...
  2. मैं वर्तमान में डिवाइस मॉडल या स्क्रीन आकार के आधार पर कुछ ह्युरिस्टिक निर्णय का उपयोग कर रहा हूं। मुझे लगता है कि यह लंबे समय तक मृत अंत है। कुछ फोन पर मेमोरी अपवाद मिला, पूरी तरह से दूसरे पर मुफ्त।
  3. क्या कोई तीसरा समाधान है, सही है?
+0

30-40 छवियों का आकार 30x50 ओओएमई का कारण नहीं बनना चाहिए। शायद आप बड़े लोड कर सकते हैं? यदि ऐसा है, तो आप उन्हें नीचे स्केल कर सकते हैं। इसके अलावा, अगर कुछ छवियों को सॉफ्ट रेफरेंस से साफ़ किया जाता है, तो उनका उपयोग नहीं किया जा रहा है, इसलिए यदि आवश्यक हो तो बस उन्हें पुनः लोड करें। –

उत्तर

8

सबसे महत्वपूर्ण प्रश्न: कर रहे हैं आप recycle()-अपने बिटमैप्स-कर रहे हैं? प्री-जिंजरब्रेड अनुप्रयोगों के लिए यह बहुत महत्वपूर्ण है (शायद पोस्ट-जिंजरब्रेड भी)।

Memory Management for Android Apps session from Google I/O 2011 को देखकर मुझे एंड्रॉइड के विकास के विशिष्टताओं की बेहतर समझ प्राप्त करने में मदद मिली।

वीडियो एक उपकरण मेट कहा जाता है कहा गया है कि - एक Memory Analyzer - जो अगर तुम याद है कि लीक किया गया है में चारों ओर फांसी वस्तुओं है निर्धारित करने के लिए उपयोगी है। यह संभवतः आपके पास 30-40 से अधिक है जो आपको लगता है कि आपके पास है।

ढेर के वर्तमान आकार को देखने और/या लॉगिंग करने के लिए, मैं this answer about Android Out of Memory exceptions में कोड का उपयोग करने का सुझाव दूंगा।

+0

लिंक के लिए धन्यवाद। मैंने उन्हें रीसायकल करने का प्रयास किया है, लेकिन इन्हें कुछ विचारों में उपयोग किया जाता है, और जब मैं उस गतिविधि पर वापस आ जाता हूं तो क्रैश का कारण बनता है। – Danail

2

सीमा उस डिवाइस पर वीएम हीप आकार से संबंधित है, जो डिवाइस पर चल रही है, क्योंकि यह डिवाइस से डिवाइस और ओएस से ओएस से अलग है, यह 16 एमबी (ऐप के लिए कुल) से 256 एमबी + तक हो सकती है (टैबलेट पर)।

आपको इसे कम अंत में रखना होगा, प्रति डिवाइस अलग-अलग बिल्ड बनाना होगा, या ऐप को रनटाइम पर जांचना होगा कि भत्ता क्या है और तदनुसार अपनी छवियों को लोड करें।

ढेर में मुक्त स्थान की मात्रा की जाँच के लिए तरीकों रहे हैं और यह आकार है:

यह API रेफरी avilable तरीकों के साथ तुम्हारी मदद करेगा:

http://developer.android.com/reference/android/app/ActivityManager.html#getMemoryClass

+0

हम्म। मुझे वहां क्या उपयोग करना चाहिए? MemoryInfo? यह कुछ हद तक मेरे लिए बाध्य दिखता है और यह देशी ढेर के बारे में है? या सामान्य ढेर? मैंने अभी तक Debug.getNativeHeapFreeSize() का उपयोग किया है, लेकिन यह अविश्वसनीय है - यह टेम्पलेटरी अधिकतम सीमा आकार देता है, यदि ऐप अधिक बिटमैप मेमोरी चाहता है तो अधिक उठाया जा सकता है। – Danail

+0

आप देशी ढेर जानकारी का उपयोग नहीं करना चाहते हैं जब तक आप स्पष्ट रूप से एनडीके का उपयोग करके मूल रूप से आवंटित नहीं कर रहे हैं। जावा वीएम एक हीप आकार देता है, कुछ ढेर आकार को कुछ फैक्ट्री कॉल, जैसे कि बिटमैप वाले लोगों द्वारा मूल रूप से आवंटित किया जा सकता है। यह आपके आवंटित वीएम हीप आकार से कटौती की जाती है, भले ही यह मूल हो, इसलिए यदि वीएम हीप 16 वर्ष का है, तो आप 4 एमबी मूल रूप से आवंटित कर सकते हैं, फिर आपके पास शेष 12 वीएम हीप में होगा। getMemoryClass() और getLargeMemoryClass() आपको उस डिवाइस द्वारा अनुमत वीएम ढेर "कक्षा" देगा जो आप चल रहे हैं। यह अधिकतम है कि आपके ऐप को आवंटित करने की अनुमति होगी। – Hamid

0

एक उच्च स्तरीय परिप्रेक्ष्य से, छवि लोडिंग और कैशिंग GreenDroid framework का हिस्सा है। इसकी जांच - पड़ताल करें।

4

छवि कैशिंग एक ऐप का एक महत्वपूर्ण हिस्सा था जिसे मैंने बनाया है और ऐप स्टोर में डाल दिया है।ऐप को छवियों को डाउनलोड करने और उन्हें स्मृति और एसडीकार्ड दोनों में कैश करने की आवश्यकता है ताकि उनका दायरा एक रन से आगे हो।

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

कम स्मृति स्थितियों के दौरान, मैंने हैश मैप जारी किया। फिर भी छवियों को अभी भी SD_Card से पुनर्प्राप्त किया जा सकता है और एक बार फिर स्मृति में कैश किया जा सकता है।

मैं रीसाइक्लिंग के बिना ऐसा करने में सक्षम था और अभी भी कोई स्मृति समस्या नहीं देख पा रहा था। जैसा कि मैं इसे समझता हूं, रीसाइक्लिंग आवश्यक नहीं है लेकिन "बिटमैप्स" के लिए उपयोग की गई स्मृति की पुरानी रिलीज को प्राप्त करने में मदद करता है क्योंकि प्री-जिंजरब्रेड ओएस में बिटमैप्स के लिए आवंटन मूल मेमोरी का उपयोग करता है। यानी स्मृति जो दल्विक ढेर का हिस्सा नहीं है। तो कचरा कलेक्टर इस स्मृति को मुक्त नहीं करता है, बल्कि इसे कार्यान्वयन विशिष्ट नीतियों से मुक्त किया जाता है। ,

public static synchronized void addImage(Bitmap b, String urlString, boolean bSaveToFile, IMAGE_TYPES eIT, boolean bForce) 
{ 
    String szKey = getKeyFromUrlString(urlString, eIT); 

    if (false == m_hmCachedImages.containsKey(szKey) || bForce) 
    { 
     m_hmCachedImages.put(szKey, b); 
     if (bSaveToFile) 
     { 
      boolean bIsNull = false; 
      // Write a null object to disk to prevent future query for non-existent image. 
      if (null == b) 
      { 
       try 
       { 
        bIsNull = true; 
        b = getNullArt(); 
       } 
       catch (NullPointerException e) 
       { 
        e.printStackTrace(); 
        throw e; 
       } 
      } 

      // Don't force null art to disk 
      if (false == File_Manager.imageExists(szKey) || (bForce && bIsNull == false)) 
       File_Manager.writeImage(b, szKey); 
     } 
    } 
} 

// यहाँ writeImage (का एक उदाहरण) File_Manager वर्ग से

public static void writeImage(Bitmap bmp, String szFileName) 
{ 
    checkStorage(); 

    if (false == mExternalStorageWriteable) 
    { 
     Log.e("FileMan", "No Writable External Device Available"); 
     return; 
    } 

    try 
    { 
     // Create dirctory if doesn't exist 
     String szFilePath = getFilesPath(); 
     boolean exists = (new File(szFilePath)).exists(); 
     if (!exists) 
     { 
      new File(szFilePath).mkdirs(); 
     } 

     // Create file 
     File file = new File(szFilePath, szFileName); 

     // Write to file 
     FileOutputStream os = new FileOutputStream(file); 
     bmp.compress(Bitmap.CompressFormat.PNG, 90, os); 
    } catch (IOException e) 
    { 
     // Unable to create file, likely because 
     // external storage is 
     // not currently mounted. 
     Log.e("FileMan", "Error writing file", e); 
    } catch (Exception e) 
    { 
     e.printStackTrace(); 
     throw e; 
    } 
} 
+0

मेरे साथ स्थिति लगभग समान है, यह बात शायद कम स्मृति की स्थिति प्रदान कर रही है । निश्चित रूप से एक मौका है कि मेरे पास मेमोरी लीक है। – Danail

-2

आप एक WebView इस्तेमाल कर सकते हैं छवियों को प्रदर्शित करने के लिए इसे कैशिंग है:

यह Cache_Manager वर्ग से है में निर्मित। इसके अलावा, यह बिना किसी विशेष कोड के 2-उंगली ज़ूम और स्क्रॉल का समर्थन करता है।

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