Android छवि कैशिंग


जवाबों:


177

और अब पंचलाइन: सिस्टम कैश का उपयोग करें।

URL url = new URL(strUrl);
URLConnection connection = url.openConnection();
connection.setUseCaches(true);
Object response = connection.getContent();
if (response instanceof Bitmap) {
  Bitmap bitmap = (Bitmap)response;
} 

ब्राउज़र के साथ साझा की गई मेमोरी और फ्लैश-रोम कैश दोनों प्रदान करता है।

grr। काश, किसी ने मुझे बताया होता कि इससे पहले कि मैं अपना कैश मैनेजर लिखता।


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

11
connection.getContent()हमेशा मेरे लिए एक InputStream देता है, मैं क्या गलत कर रहा हूँ?
टायलर Collier

3
अगर मैं अब कैश के लिए सामग्री पर एक समाप्ति तिथि निर्धारित कर सकता हूं तो मेरा जीवन इतना आसान हो जाएगा :)
Janusz

11
@Scienceprodigy कोई विचार नहीं है कि बिटमैपलडर क्या है, निश्चित रूप से किसी भी मानक एंड्रॉइड लाइब्रेरी में नहीं है जिसे मैं जानता हूं, लेकिन यह कम से कम मुझे सही दिशा में ले गया। Bitmap response = BitmapFactory.decodeStream((InputStream)connection.getContent());
स्टीफन फूहरी

6
कैश को काम करने के लिए आपको जो अतिरिक्त कदम उठाने की आवश्यकता है, उसके बारे में नीचे दिए गए जो के उत्तर को अवश्य देखें
कीथ

65

connection.setUseCachesऊपर के सुरुचिपूर्ण समाधान के बारे में : दुख की बात है, यह कुछ अतिरिक्त प्रयास के बिना काम नहीं करेगा। आपको एक ResponseCacheप्रयोग स्थापित करने की आवश्यकता होगी ResponseCache.setDefault। अन्यथा, HttpURLConnectionचुपचाप setUseCaches(true)बिट को नजरअंदाज कर देगा ।

विवरण के लिए टिप्पणियों को सबसे ऊपर FileResponseCache.javaदेखें:

http://libs-for-android.googlecode.com/svn/reference/com/google/android/filecache/FileResponseCache.html

(मैं इसे एक टिप्पणी में पोस्ट करूंगा, लेकिन मेरे पास स्पष्ट रूप से पर्याप्त कर्म नहीं है।)



2
जब आप एक का उपयोग करते हैं HttpResponseCache, तो आप HttpResponseCache.getHitCount()रिटर्निंग ० प्राप्त कर सकते हैं । मुझे यकीन नहीं है, लेकिन मुझे लगता है कि ऐसा इसलिए है क्योंकि आप जिस वेबसर्वर से अनुरोध कर रहे हैं, वह उस स्थिति में कैशिंग हेडर का उपयोग नहीं करता है। वैसे भी कैशिंग कार्य करने के लिए, उपयोग करें connection.addRequestProperty("Cache-Control", "max-stale=" + MAX_STALE_CACHE);
अल्मर १

1
Google कोड खोज लिंक मृत है (फिर से?), कृपया लिंक को अपडेट करें।
फेलिक्स डी।

इसके अलावा, मुझे यकीन नहीं है कि यह व्यवहार अब तय हो गया है या नहीं। किसी कारण से सर्वर से 304 लौटाने से .getContent()विधि का उपयोग करते समय एचयूसी लटका होगा क्योंकि 304 प्रतिक्रियाओं में आरएफसी मानक द्वारा संबद्ध प्रतिक्रिया निकाय नहीं है।
TheRealChx101

27

उन्हें बिटमैप में परिवर्तित करें और फिर उन्हें एक संग्रह (हैशपॉप, सूची आदि) में संग्रहीत करें या आप उन्हें एसडीकार्ड पर लिख सकते हैं।

जब पहले दृष्टिकोण का उपयोग करके उन्हें एप्लिकेशन स्पेस में संग्रहीत किया जाता है, तो आप उन्हें java.lang.ref.oft.SoftReference के आसपास लपेटना चाह सकते हैं, खासकर यदि उनकी संख्या बड़ी है (ताकि वे संकट के दौरान एकत्र किए गए कचरा हों)। यह हालांकि एक रीलोड जारी कर सकता है।

HashMap<String,SoftReference<Bitmap>> imageCache =
        new HashMap<String,SoftReference<Bitmap>>();

एसडीकार्ड पर उन्हें लिखने के लिए एक रिलोड की आवश्यकता नहीं होगी; सिर्फ एक उपयोगकर्ता-अनुमति।


हम एसडी या फोन मेमोरी पर छवि कैसे लिख सकते हैं?
d-man

एसडी कार्ड पर छवियों को बचाने के लिए: आप या तो सामान्य फ़ाइल I / O संचालन का उपयोग करके रिमोट सर्वर से पढ़ी गई छवि स्ट्रीम को मेमोरी में कर सकते हैं या यदि आपने अपनी छवियों को बिटमैप ऑब्जेक्ट में परिवर्तित कर दिया है तो आप Bitmap.compress () विधि का उपयोग कर सकते हैं।
सामुह

@ d-man मैं पहले डिस्क को लिखने और फिर एक Uriपथ संदर्भ प्राप्त करने का सुझाव दूंगा जिसे आप ImageViewऔर अन्य कस्टम दृश्यों को पास कर सकते हैं । क्योंकि हर बार आप compressगुणवत्ता खो देंगे। बेशक यह केवल हानिपूर्ण एल्गोरिदम के लिए सच है। यह विधि आपको फ़ाइल के हैश को स्टोर करने की अनुमति भी देती है और अगली बार जब आप सर्वर If-None-Matchऔर ETagहेडर के माध्यम से फाइल के लिए अनुरोध करते हैं तो इसका उपयोग कर सकते हैं ।
TheRealChx101

@ TheRealChx101 क्या आप यह समझने में मदद कर सकते हैं कि अगली बार जब आप सर्वर से फाइल के लिए आई-नो-मैच और ईटैग हेडर के माध्यम से अनुरोध करते हैं , तो मैं मूल रूप से समाधान दृष्टिकोण की तलाश कर रहा हूं, जहां छवि को परिभाषित के लिए फ़ॉर्म स्थानीय कैश का उपयोग करने के लिए रहना चाहिए। अवधि या यदि इसे प्राप्त नहीं किया जा सकता है तो जब भी URL के लिए सामग्री में परिवर्तन हो, उसे नवीनतम के साथ आवेदन में प्रतिबिंबित करना चाहिए और उसे कैश करना चाहिए।
CoDe

@CoDe अभी के लिए इस लिंक पर जाएँ, android.jlelse.eu/…
TheRealChx101

27

LruCacheकुशलतापूर्वक कैश छवियों का उपयोग करें । आप Android डेवलपर साइटLruCache से पढ़ सकते हैं

मैंने Android में Images Download और caching के लिए नीचे दिए गए समाधान का उपयोग किया है। आप नीचे दिए गए चरणों का अनुसरण कर सकते हैं:

चरण 1: कक्षा नामांकित करें ImagesCache। मैंने उपयोग किया हैSingleton object for this class

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

public class ImagesCache 
{
    private  LruCache<String, Bitmap> imagesWarehouse;

    private static ImagesCache cache;

    public static ImagesCache getInstance()
    {
        if(cache == null)
        {
            cache = new ImagesCache();
        }

        return cache;
    }

    public void initializeCache()
    {
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() /1024);

        final int cacheSize = maxMemory / 8;

        System.out.println("cache size = "+cacheSize);

        imagesWarehouse = new LruCache<String, Bitmap>(cacheSize)
                {
                    protected int sizeOf(String key, Bitmap value) 
                    {
                        // The cache size will be measured in kilobytes rather than number of items.

                        int bitmapByteCount = value.getRowBytes() * value.getHeight();

                        return bitmapByteCount / 1024;
                    }
                };
    }

    public void addImageToWarehouse(String key, Bitmap value)
    {       
        if(imagesWarehouse != null && imagesWarehouse.get(key) == null)
        {
            imagesWarehouse.put(key, value);
        }
    }

    public Bitmap getImageFromWarehouse(String key)
    {
        if(key != null)
        {
            return imagesWarehouse.get(key);
        }
        else
        {
            return null;
        }
    }

    public void removeImageFromWarehouse(String key)
    {
        imagesWarehouse.remove(key);
    }

    public void clearCache()
    {
        if(imagesWarehouse != null)
        {
            imagesWarehouse.evictAll();
        }       
    }

}

चरण 2:

DownloadImageTask नाम का एक और वर्ग बनाते हैं जिसका उपयोग अगर बिटमैप कैश में उपलब्ध नहीं है तो इसे यहाँ से डाउनलोड किया जाएगा:

public class DownloadImageTask extends AsyncTask<String, Void, Bitmap>
{   
    private int inSampleSize = 0;

    private String imageUrl;

    private BaseAdapter adapter;

    private ImagesCache cache;

    private int desiredWidth, desiredHeight;

    private Bitmap image = null;

    private ImageView ivImageView;

    public DownloadImageTask(BaseAdapter adapter, int desiredWidth, int desiredHeight) 
    {
        this.adapter = adapter;

        this.cache = ImagesCache.getInstance();

        this.desiredWidth = desiredWidth;

        this.desiredHeight = desiredHeight;
    }

    public DownloadImageTask(ImagesCache cache, ImageView ivImageView, int desireWidth, int desireHeight)
    {
        this.cache = cache;

        this.ivImageView = ivImageView;

        this.desiredHeight = desireHeight;

        this.desiredWidth = desireWidth;
    }

    @Override
    protected Bitmap doInBackground(String... params) 
    {
        imageUrl = params[0];

        return getImage(imageUrl);
    }

    @Override
    protected void onPostExecute(Bitmap result) 
    {
        super.onPostExecute(result);

        if(result != null)
        {
            cache.addImageToWarehouse(imageUrl, result);

            if(ivImageView != null)
            {
                ivImageView.setImageBitmap(result);
            }
            else if(adapter != null)
            {
                adapter.notifyDataSetChanged();
            }
        }
    }

    private Bitmap getImage(String imageUrl)
    {   
        if(cache.getImageFromWarehouse(imageUrl) == null)
        {
            BitmapFactory.Options options = new BitmapFactory.Options();

            options.inJustDecodeBounds = true;

            options.inSampleSize = inSampleSize;

            try
            {
                URL url = new URL(imageUrl);

                HttpURLConnection connection = (HttpURLConnection)url.openConnection();

                InputStream stream = connection.getInputStream();

                image = BitmapFactory.decodeStream(stream, null, options);

                int imageWidth = options.outWidth;

                int imageHeight = options.outHeight;

                if(imageWidth > desiredWidth || imageHeight > desiredHeight)
                {   
                    System.out.println("imageWidth:"+imageWidth+", imageHeight:"+imageHeight);

                    inSampleSize = inSampleSize + 2;

                    getImage(imageUrl);
                }
                else
                {   
                    options.inJustDecodeBounds = false;

                    connection = (HttpURLConnection)url.openConnection();

                    stream = connection.getInputStream();

                    image = BitmapFactory.decodeStream(stream, null, options);

                    return image;
                }
            }

            catch(Exception e)
            {
                Log.e("getImage", e.toString());
            }
        }

        return image;
    }

चरण 3: अपने Activityया से उपयोगAdapter

नोट: यदि आप Activityकक्षा से url से छवि लोड करना चाहते हैं । दूसरे कंस्ट्रक्टर का उपयोग करें DownloadImageTask, लेकिन यदि आप Adapterपहले कंस्ट्रक्टर के उपयोग से छवि प्रदर्शित करना चाहते हैं DownloadImageTask(उदाहरण के लिए आपके पास एक छवि है ListViewऔर आप 'एडेप्टर' से छवि सेट कर रहे हैं)

गतिविधि से उपयोग:

ImageView imv = (ImageView) findViewById(R.id.imageView);
ImagesCache cache = ImagesCache.getInstance();//Singleton instance handled in ImagesCache class.
cache.initializeCache();

String img = "your_image_url_here";

Bitmap bm = cache.getImageFromWarehouse(img);

if(bm != null)
{
  imv.setImageBitmap(bm);
}
else
{
  imv.setImageBitmap(null);

  DownloadImageTask imgTask = new DownloadImageTask(cache, imv, 300, 300);//Since you are using it from `Activity` call second Constructor.

  imgTask.execute(img);
}

ADAPTER से उपयोग:

ImageView imv = (ImageView) rowView.findViewById(R.id.imageView);
ImagesCache cache = ImagesCache.getInstance();
cache.initializeCache();

String img = "your_image_url_here";

Bitmap bm = cache.getImageFromWarehouse(img);

if(bm != null)
{
  imv.setImageBitmap(bm);
}
else
{
  imv.setImageBitmap(null);

  DownloadImageTask imgTask = new DownloadImageTask(this, 300, 300);//Since you are using it from `Adapter` call first Constructor.

  imgTask.execute(img);
}

ध्यान दें:

cache.initializeCache()आप इस कथन का उपयोग अपने आवेदन की पहली गतिविधि में कर सकते हैं। एक बार जब आप कैश को इनिशियलाइज़ कर लेते हैं तो आपको हर बार इसे इनिशियलाइज़ करने की आवश्यकता नहीं होगी यदि आप ImagesCacheइंस्टेंस का उपयोग कर रहे हैं ।

मैं चीजों को समझाने में कभी भी अच्छा नहीं हूं लेकिन आशा करता हूं कि यह शुरुआती लोगों की मदद करेगा कि कैसे LruCacheऔर इसके उपयोग को कैश किया जाए :)

संपादित करें:

अब एक दिन बहुत ही प्रसिद्ध पुस्तकालयों के रूप में जाना जाता है Picassoऔर Glideजिसका उपयोग एंड्रॉइड ऐप में बहुत कुशलता से छवियों को लोड करने के लिए किया जा सकता है। Android और Glide For Android के लिए यह बहुत ही सरल और उपयोगी लाइब्रेरी पिकासो आज़माएँ । आपको कैश छवियों के बारे में चिंता करने की आवश्यकता नहीं है।

पिकासो आपके आवेदन में परेशानी मुक्त छवि लोड करने की अनुमति देता है - अक्सर कोड की एक पंक्ति में!

ग्लाइड, पिकासो की तरह, कई स्रोतों से छवियों को लोड और प्रदर्शित कर सकते हैं, जबकि कैशिंग का भी ध्यान रखते हैं और छवि हेरफेर करते समय कम मेमोरी प्रभाव रखते हैं। इसका उपयोग आधिकारिक Google ऐप द्वारा किया गया है (जैसे Google I / O 2015 के लिए ऐप) और पिकासो की तरह ही लोकप्रिय है। इस श्रृंखला में, हम पिकासो पर ग्लाइड के मतभेदों और लाभों का पता लगाने जा रहे हैं।

आप ग्लाइड और पिकासो के बीच अंतर के लिए ब्लॉग पर भी जा सकते हैं


3
बकाया उत्तर और स्पष्टीकरण! मुझे लगता है कि यह सबसे अच्छा समाधान है क्योंकि यह ऑफ़लाइन होने पर काम करता है और Android LruCache का उपयोग करता है। मैंने पाया कि एड्रोलैंड का समाधान जो के जोड़ के साथ भी हवाई जहाज मोड में काम नहीं करता था जिसे एकीकृत करने के लिए अधिक प्रयास की आवश्यकता थी। Btw, ऐसा लगता है कि एंड्रॉइड या नेटवर्क कैशिंग की एक महत्वपूर्ण राशि प्रदान करता है, भले ही आप अतिरिक्त कुछ न करें। (एक मामूली नाइट: नमूना उपयोग के लिए GetImageFromWareHouse, 'H' को मैच करने के लिए लोअरकेस होना चाहिए।) धन्यवाद!
एडविन इवांस

1
महान स्पष्टीकरण :)
XtreemDeveloper

क्या आप getImage () विधि की व्याख्या कर सकते हैं, विशेष रूप से यह छवि के आकार का क्या करता है और यह कैसे होता है। मुझे समझ में नहीं आता है कि आप फ़ंक्शन को फिर से अपने अंदर क्यों बुलाते हैं और यह कैसे काम करता है।
ग्रीशेक

1
उस के लिए Upvote if(cache == null)जिसने मेरी समस्या हल कर दी! :)
MR। गार्सिया

1
अंत में मेरा संपादित उत्तर भी देखें। मैंने आजकल अधिकांश डेवलपर्स द्वारा उपयोग किए जाने वाले प्रसिद्ध पुस्तकालयों के बारे में उल्लेख किया है। उन पिकासो को आज़माएँ: square.github.io/picasso और Glide: futurestud.io/blog/glide-getting-started
ज़ुबैर अहमद

18

एक छवि डाउनलोड करने और मेमोरी कार्ड में सहेजने के लिए आप इसे इस तरह से कर सकते हैं।

//First create a new URL object 
URL url = new URL("http://www.google.co.uk/logos/holiday09_2.gif")

//Next create a file, the example below will save to the SDCARD using JPEG format
File file = new File("/sdcard/example.jpg");

//Next create a Bitmap object and download the image to bitmap
Bitmap bitmap = BitmapFactory.decodeStream(url.openStream());

//Finally compress the bitmap, saving to the file previously created
bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(file));

अपने मैनिफ़ेस्ट में इंटरनेट की अनुमति जोड़ना न भूलें:

<uses-permission android:name="android.permission.INTERNET" />

10
आप JPEG को डिकोड क्यों कर रहे हैं और फिर इसे फिर से एन्कोडिंग कर रहे हैं? आपको URL को बाइट सरणी में डाउनलोड करना बेहतर है, फिर उस बाइट सरणी का उपयोग करके अपना बिटमैप बनाएं और फ़ाइल में लिखें। हर बार जब आप JPEG को डीकोड और री-एनकोड करते हैं, तो छवि की गुणवत्ता खराब हो जाती है।
कॉमन्सवेयर

2
फेयर प्वाइंट, स्पीड के लिए ज्यादा था तो कुछ भी। हालाँकि, यदि एक बाइट सरणी के रूप में सहेजा गया है और स्रोत फ़ाइल JPEG नहीं थी, तो फ़ाइल को किसी भी रूप में परिवर्तित करने की आवश्यकता नहीं होगी? SDK रिटर्न्स से "decodeByteArray" डीकोड बिटमैप, या नल यदि छवि डेटा को डीकोड नहीं किया जा सकता है "तो इससे मुझे लगता है कि यह हमेशा इमेज डेटा को डिकोड कर रहा है इसलिए इसे फिर से एन्कोडिंग की आवश्यकता नहीं होगी?
लेज्डसन

दक्षता की बात करें, तो क्या यह कारगर नहीं होगा यदि फाइलऑउटपुट स्ट्रीम से गुजरने के बजाए हम बफ़रऑउटपुट स्ट्रेस को पास करें?
सामुहिक

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

50mb की एपीके सीमा के साथ, अब एसडी कार्ड के लिए कैशिंग डेवलपर्स के लिए एकमात्र तरीका हो सकता है।
Ljdawson

13

मैं droidfu की छवि कैश का उपयोग करने पर विचार करूंगा। यह इन-मेमोरी और डिस्क-आधारित छवि कैश दोनों को लागू करता है। आपको एक WebImageView भी मिलता है जो ImageCache लाइब्रेरी का लाभ उठाता है।

यहाँ droidfu और WebImageView का पूरा विवरण दिया गया है: http://brainflush.wordpress.com/2009/11/23/droid-fu-part-2-webimageview-and-webgalleryadcape/


उन्होंने 2010 के बाद से अपने कोड को वापस ले लिया है; यहाँ मूल लिंक है: github.com/kaeppler/droid-fu
esilver

3
वह लिंक अभी भी काम नहीं करता है। मैंने एक ऐसी ही लाइब्रेरी लिखी है जिसका नाम है Android- ImageManager github.com/felipecsl/Android-ImageManager
फेलिप लीमा

9

मैंने SoftReferences की कोशिश की है, वे एंड्रॉइड में बहुत आक्रामक रूप से पुन: प्रशंसित हैं कि मुझे लगा कि उनका उपयोग करने का कोई मतलब नहीं था


2
सहमत - मेरे द्वारा परीक्षण किए गए उपकरणों पर सॉफ्टराइफ़र्स बहुत जल्दी पुनः प्राप्त हो जाते हैं
7

3
Google ने खुद इस बात की पुष्टि की है कि SoftReferenceएस एकत्रित करने पर Dalvik की GC बहुत आक्रामक है । वे LruCacheइसके बजाय उनके उपयोग की सलाह देते हैं ।
काक

9

जैसा कि थंडर रैबिट ने सुझाव दिया था, ImageDownloader नौकरी के लिए सबसे अच्छा है। मुझे कक्षा में थोड़ा बदलाव भी आया:

http://theandroidcoder.com/utilities/android-image-download-and-caching/

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


7

जोए का यह एक अच्छा कैच है। ऊपर दिए गए कोड के उदाहरण में दो समस्याएं हैं - एक - प्रतिक्रिया ऑब्जेक्ट बिटमैप का उदाहरण नहीं है (जब मेरा URL एक ऐसे संदर्भ संदर्भित करता है जैसे http: \ website.com \ image.jpg, इसका एक

org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl $ LimitedInputStream)।

दूसरा, जैसा कि जो बताते हैं, कोई कैशिंग प्रतिक्रिया कैश को कॉन्फ़िगर किए बिना नहीं होता है। एंड्रॉइड डेवलपर्स को अपने स्वयं के कैश को रोल करने के लिए छोड़ दिया जाता है। यहां ऐसा करने के लिए एक उदाहरण है, लेकिन यह केवल स्मृति में कैश करता है, जो वास्तव में पूर्ण समाधान नहीं है।

http://codebycoffee.com/2010/06/29/using-responsecache-in-an-android-app/

URLConnection कैशिंग API यहां वर्णित है:

http://download.oracle.com/javase/6/docs/technotes/guides/net/http-cache.html

मुझे अभी भी लगता है कि यह इस मार्ग पर जाने के लिए एक ठीक समाधान है - लेकिन आपको अभी भी कैश लिखना होगा। मज़ा की तरह लगता है, लेकिन मैं सुविधाओं लिखना होगा।


7

इसके बारे में Android के आधिकारिक प्रशिक्षण अनुभाग में एक विशेष प्रविष्टि है: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

अनुभाग काफी नया है, यह तब नहीं था जब सवाल पूछा गया था।

सुझाया गया समाधान एक LruCache का उपयोग करना है। उस वर्ग को हनीकॉम्ब पर पेश किया गया था, लेकिन यह संगतता पुस्तकालय पर भी शामिल है।

आप अधिकतम संख्या या प्रविष्टियाँ सेट करके एक LruCache को इनिशियलाइज़ कर सकते हैं और यह स्वचालित रूप से आपको आपकी तरह छाँट देगा और सीमा से अधिक होने पर कम उपयोग किए गए लोगों को साफ़ कर देगा। इसके अलावा यह एक सामान्य मानचित्र के रूप में उपयोग किया जाता है।

आधिकारिक पृष्ठ से नमूना कोड:

private LruCache mMemoryCache;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    // Get memory class of this device, exceeding this amount will throw an
    // OutOfMemory exception.
    final int memClass = ((ActivityManager) context.getSystemService(
            Context.ACTIVITY_SERVICE)).getMemoryClass();

    // Use 1/8th of the available memory for this memory cache.
    final int cacheSize = 1024 * 1024 * memClass / 8;

    mMemoryCache = new LruCache(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in bytes rather than number of items.
            return bitmap.getByteCount();
        }
    };
    ...
}

public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
    if (getBitmapFromMemCache(key) == null) {
        mMemoryCache.put(key, bitmap);
    }
}

public Bitmap getBitmapFromMemCache(String key) {
    return mMemoryCache.get(key);
}

पहले SoftReferences एक अच्छा विकल्प थे, लेकिन अब आधिकारिक पृष्ठ से उद्धृत नहीं:

नोट: अतीत में, एक लोकप्रिय मेमोरी कैश कार्यान्वयन एक सॉफ्टरेंफरेंस या वीकररेंस बिटमैप कैश था, हालांकि यह अनुशंसित नहीं है। एंड्रॉइड 2.3 (एपीआई लेवल 9) से शुरू होने वाले कचरा कलेक्टर नरम / कमजोर संदर्भों को इकट्ठा करने के साथ अधिक आक्रामक होते हैं जो उन्हें काफी अप्रभावी बनाता है। इसके अलावा, एंड्रॉइड 3.0 (एपीआई स्तर 11) से पहले, बिटमैप के बैकिंग डेटा को देशी मेमोरी में संग्रहीत किया गया था, जो कि एक पूर्वसूचक तरीके से जारी नहीं किया गया है, संभवतः किसी एप्लिकेशन को इसकी मेमोरी सीमा और क्रैश से अधिक हो सकता है।


3

सर्गेई तारासेविच द्वारा यूनिवर्सल इमेज लोडर लाइब्रेरी का उपयोग करने पर विचार करें । यह इसके साथ आता है:

  • मल्टीथ्रेड छवि लोड हो रहा है। यह आपको थ्रेड पूल के आकार को परिभाषित कर सकता है
  • डिवाइस की फ़ाइल sytem और SD कार्ड में मेमोरी में इमेज कैशिंग।
  • लोडिंग प्रगति और लोडिंग घटनाओं को सुनने के लिए संभावना

यूनिवर्सल इमेज लोडर निम्नलिखित कैश कॉन्फ़िगरेशन के साथ, डाउनलोड की गई छवियों के लिए विस्तृत कैश प्रबंधन की अनुमति देता है:

  • UsingFreqLimitedMemoryCache: कैश आकार की सीमा पार होने पर कम से कम अक्सर उपयोग किए जाने वाले बिटमैप को हटा दिया जाता है।
  • LRULimitedMemoryCache: कैश आकार की सीमा पार होने पर हाल ही में उपयोग किया गया बिटमैप हटा दिया जाता है।
  • FIFOLimitedMemoryCache: कैश आकार की सीमा पार होने पर फीफो नियम को हटाने के लिए उपयोग किया जाता है।
  • LargestLimitedMemoryCache: कैश आकार की सीमा पार होने पर सबसे बड़ा बिटमैप हटा दिया जाता है।
  • LimitedAgeMemoryCache: कैश्ड ऑब्जेक्ट तब हटा दिया जाता है जब उसकी आयु निर्धारित मान से अधिक हो जाती है
  • WeakMemoryCache: बिटमैप्स के केवल कमजोर संदर्भों के साथ एक मेमोरी कैश।

एक सरल उपयोग उदाहरण:

ImageView imageView = groupView.findViewById(R.id.imageView);
String imageUrl = "http://site.com/image.png"; 

ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
imageLoader.displayImage(imageUrl, imageView);

यह उदाहरण डिफ़ॉल्ट का उपयोग करता है UsingFreqLimitedMemoryCache


जब गहन रूप से उपयोग किया जाता है, तो यूनिवर्सल इमेज लोडर मेमोरी लीक का कारण बन जाएगा। मुझे संदेह है कि ऐसा इसलिए होता है क्योंकि यह कोड में सिंगललेटन्स का उपयोग करता है (उदाहरण में 'getInstance ()' देखें)। बहुत सारी छवियों को लोड करने और फिर एक-दो बार मेरी स्क्रीन को घुमाने के बाद, मेरा ऐप हर समय दुर्घटनाग्रस्त हो गया क्योंकि यूआईएल में आउटऑफ़मैरीऑयर्स। यह एक महान पुस्तकालय है, लेकिन यह एक प्रसिद्ध तथ्य है कि आपको कभी-कभी
एकल

1
जब आप जानते हैं कि कैसे का उपयोग करें! :)
रेनेटिक

3

मेरे लिए वास्तव में जो काम किया गया वह मेरे मुख्य वर्ग पर ResponseCache की स्थापना कर रहा था:

try {
   File httpCacheDir = new File(getApplicationContext().getCacheDir(), "http");
   long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
   HttpResponseCache.install(httpCacheDir, httpCacheSize);
} catch (IOException e) { } 

तथा

connection.setUseCaches(true);

बिटमैप डाउनलोड करते समय।

http://practicaldroid.blogspot.com/2013/01/utilizing-http-response-cache.html


क्या यह संभव नहीं है कि मैं लेप्रूचेस को कैनप्रोसेन्सेचे के साथ प्रयोग कर सकूं
iOSAndroidWindowsMobileAppsDev


1

मैं कुछ समय से इससे कुश्ती कर रहा था; SoftReferences का उपयोग करने वाले उत्तर उनके डेटा को बहुत तेज़ी से खो देंगे। उन अनुरोधों के बारे में जो सुझाव देते हैं कि रिक्वेस्ट कैश करने में बहुत गड़बड़ हो गई थी, साथ ही मुझे कभी भी इसका पूरा उदाहरण नहीं मिला।

लेकिन ImageDownloader.java मेरे लिए अद्भुत काम करता है। क्षमता तक पहुंचने तक या शुद्ध समय समाप्त होने तक यह एक हैशपॉप का उपयोग करता है, फिर चीजें सॉफ्टरफेन्स में स्थानांतरित हो जाती हैं, जिससे दोनों दुनिया का सबसे अच्छा उपयोग होता है।



0

यहां तक ​​कि बाद में जवाब दिया, लेकिन मैंने एक एंड्रॉइड इमेज मैनेजर लिखा जो कैशिंग को पारदर्शी रूप से (मेमोरी और डिस्क) हैंडल करता है। कोड Github https://github.com/felipecsl/Android-ImageManager पर है


1
मैंने इसे एक ListView में जोड़ा और यह बहुत अच्छी तरह से संभालना प्रतीत नहीं होता है। क्या ListViews के लिए कुछ विशेष कार्यान्वयन है?

0

: स्वर्गीय जवाब है, लेकिन मुझे लगता है मैं अपनी साइट के लिए एक लिंक जोड़ना चाहिए क्योंकि मैं एक ट्यूटोरियल के लिए एंड्रॉयड एक छवि कैश करने के लिए लिखा है सोचा http://squarewolf.nl/2010/11/android-image-cache/ अद्यतन: स्रोत पुराना होने के कारण पृष्ठ को ऑफ़लाइन ले लिया गया है। मैं इग्निशन का उपयोग करने के लिए उसकी सलाह में @elenasys से जुड़ता हूं ।

तो उन सभी लोगों के लिए जो इस प्रश्न पर ठोकर खाते हैं और उन्होंने कोई हल नहीं निकाला है: आशा है कि आप आनंद लेंगे! = D


0

उत्तर देर से लेकिन मुझे लगता है कि यह पुस्तकालय कैशिंग छवियों के साथ बहुत मदद करेगा: https://github.com/crypticminds/ColdStorage

बस छवि को @LoadCache (R.id.id_of_my_image_view, "URL_to_downlaod_image_from) के साथ एनोटेट करें और यह छवि को डाउनलोड करने और छवि दृश्य में लोड करने का ध्यान रखेगा। आप एक प्लेसहोल्डर छवि और लोडिंग एनीमेशन भी निर्दिष्ट कर सकते हैं।

एनोटेशन का विस्तृत दस्तावेज यहां मौजूद है: - https://github.com/crypticminds/ColdStorage/wiki/@LoadImage-annotation

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.