2010-06-21 12 views
11

मैं डाउनलोड छवि कैशिंग के लिए एक छवि कैश सिस्टम लागू कर रहा हूं।एंड्रॉइड: छवि कैश रणनीति और मेमोरी कैश आकार

मेरी रणनीति दो-स्तर के कैश पर आधारित है: मेमोरी-स्तर और डिस्क-स्तर।

मेरी कक्षा बहुत एक SoftRererence ऑब्जेक्ट के अंदर लपेटा जाता है वर्ग droidfu project

में इस्तेमाल किया और बिटमैप objet मेरे डाउनलोड की गई छवियां एक hashmap में डाल दिया जाता है के समान है। इसके अलावा प्रत्येक छवि डिस्क पर स्थायी रूप से सहेजी जाती है। यदि कोई अनुरोधित छवि Hashmap<String,SoftReference<Bitmap>> में नहीं मिली है तो इसे डिस्क पर पढ़ा जाएगा, और उसके बाद हैशैप में वापस धक्का दिया जाएगा। अन्यथा छवि नेटवर्क से डाउनलोड की जाएगी।

private void checkCacheUsage() { 

     long size = 0; 
     final File[] fileList = new File(mCacheDirPath).listFiles(); 
     Arrays.sort(fileList, new Comparator<File>() { 
      public int compare(File f1, File f2) { 
       return Long.valueOf(f2.lastModified()).compareTo(
         f1.lastModified()); 
      } 
     }); 
     for (File file : fileList) { 
      size += file.length(); 
      if (size > MAX_DISK_CACHE_SIZE) { 
       file.delete(); 
       Log.d(ImageCache.class.getSimpleName(), 
         "checkCacheUsage: Size exceeded " + size + "(" 
           + MAX_DISK_CACHE_SIZE + ") wiping older file {"+file.toString()+"}"); 
      } 
     } 

    } 

यह विधि एक डिस्क लेखन afte कुछ समय कहा जाता है:: जब से मैं phisical डिवाइस momery में छवियों की दुकान, मैं डिवाइस अंतरिक्ष संरक्षण और कब्जे वाले अंतरिक्ष के एक 1M के तहत रहने के लिए एक जांच को शामिल किया है

Random r = new Random(); 
     int ra = r.nextInt(10); 

     if (ra % 2 == 0){ 
      checkCacheUsage(); 
     } 

मैं जो जोड़ना चाहता हूं वह हैशैप आकार पर एक ही जांच है ताकि इसे बहुत अधिक बढ़ने से रोका जा सके। कुछ इस तरह:

private synchronized void checkMemoryCacheUsage(){ 

      long size = 0; 

      for (SoftReference<Bitmap> a : cache.values()) { 

       final Bitmap b = a.get(); 

       if (b != null && ! b.isRecycled()){ 
        size += b.getRowBytes() * b.getHeight(); 
       } 

       if (size > MAX_MEMORY_SIZE){ 
        //Remove some elements from the cache 
       } 

      } 

      Log.d(ImageCache.class.getSimpleName(), 
        "checkMemoryCacheUsage: " + size + " in memory"); 

    } 

मेरा प्रश्न है: क्या एक सही MAX_MEMORY_SIZE मूल्य हो सकता है? इसके अलावा, क्या यह एक अच्छा दृष्टिकोण है? एक अच्छा जवाब भी हो सकता है: "ऐसा मत करो! सॉफ्ट रेफरेंस पहले से ही पर्याप्त है"

+0

इस एपीआई http विचार कर सकते हैं: //docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/cache/CacheBuilder.html – carfield

उत्तर

8

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

+0

एंड्रॉइड नरम संदर्भों को इस तरह से लागू करता है जो बनाता है यह इस तरह के कैशिंग के लिए अनुपयुक्त है। अधिक जानकारी के लिए यह बग रिपोर्ट देखें: http://code.google.com/p/android/issues/detail?id=20015&can=1&q=softReference&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars। छवियों को स्मृति से हटा दिया जाएगा, फिलहाल वे केवल सॉफ्ट रेफरेंस के माध्यम से पहुंच योग्य हैं। Google टीम एलआरयू कैश के उपयोग की सिफारिश करती है। यहां समस्या कैश के अधिकतम आकार को निर्धारित करने के लिए है। – Janusz

+0

@ जैनुस, यह बहुत सच है। लेकिन चूंकि कोई एलआरयू कैश कार्यान्वयन नहीं है क्योंकि प्रत्येक शुरुआती लोग ले सकते हैं और पुन: उपयोग कर सकते हैं उन्हें सॉफ्ट रेफरेंस से शुरुआत करना है। यह सही नहीं है (मुझे उस मुद्दे के बारे में पता है जिसके बारे में आप बात कर रहे हैं) लेकिन यह शुरू करने के लिए काफी अच्छा है। – Fedor

+0

मुझे नहीं लगता कि यह शुरू करने के लिए पर्याप्त गुग है। गति के साथ स्मृति को इस समय मुक्त किया जाता है नरम संदर्भ बेकार होते हैं और बहुत भ्रम पैदा करते हैं। उनका उपयोग करने के लिए बिल्कुल कुछ भी नहीं है। – Janusz

1

मैं छवि कैश के लिए ढेर का एक-तिहाई उपयोग कर रहा हूं।

int memoryInMB = activityManager.getMemoryClass(); 
long totalAppHeap = memoryInMB * 1024 * 1024; 
int runtimeCacheLimit = (int)totalAppHeap/3; 

वैसे, एंड्रॉइड सॉफ्ट संदर्भ में मुलायम संदर्भ के बारे में आप अपेक्षा करते हैं कि काम नहीं करते हैं। एक प्लेटफॉर्म मुद्दा है कि नरम संदर्भ बहुत जल्दी एकत्र किए जाते हैं, भले ही बहुत सारी मेमोरी मुक्त हो।

चेक http://code-gotcha.blogspot.com/2011/09/softreference.html

0

मैं अपने बढ़ाया बिटमैप्स, दोनों मेमोरी और डिस्क कैश उदाहरण के लिए अलग कैशिंग प्रणाली में देख रहा हूँ। उदाहरण जो मेरी जरूरतों के लिए जटिल हैं, इसलिए मैंने LruCache का उपयोग करके अपना स्वयं का बिटमैप मेमोरी कैश बना दिया। आपके पास चालू कोड-उदाहरण here को देखने या इस कोड का उपयोग कर सकते हैं:

मेमोरी कैश:

public class Cache { 
    private static LruCache<Integer, Bitmap> bitmaps = new BitmapLruCache(); 

    public static Bitmap get(int drawableId){ 
     Bitmap bitmap = bitmaps.get(drawableId); 
     if(bitmap != null){ 
      return bitmap; 
     } else { 
      bitmap = SpriteUtil.createScaledBitmap(drawableId); 
      bitmaps.put(drawableId, bitmap); 
      return bitmap; 
     } 
    } 
} 

BitmapLruCache:

public class BitmapLruCache extends LruCache<Integer, Bitmap> { 
    private final static int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 
    private final static int cacheSize = maxMemory/2; 

    public BitmapLruCache() { 
     super(cacheSize); 
    } 

    @Override 
    protected int sizeOf(Integer key, Bitmap bitmap) { 
     // The cache size will be measured in kilobytes rather than number of items. 
     return bitmap.getRowBytes() * bitmap.getHeight()/1024; 
    } 
} 
संबंधित मुद्दे