Buforowanie obrazu Androida

141

Jak mogę buforować obrazy po ich pobraniu z sieci?

d-man
źródło

Odpowiedzi:

177

A teraz puenta: użyj pamięci podręcznej systemu.

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

Zapewnia pamięć podręczną i pamięć podręczną flash-rom, współdzielone z przeglądarką.

grr. Żałuję, że ktoś mi to nie powiedział, zanim napisałem własnego menedżera pamięci podręcznej.

edrowland
źródło
1
Wow, to był niesamowicie elegancki sposób na zrobienie tego, wielkie dzięki. W żaden sposób nie jest wolniejszy niż mój prosty menedżer pamięci podręcznej, a teraz nie muszę wykonywać porządków w folderze karty SD.
Kevin Przeczytaj
11
connection.getContent()zawsze zwraca dla mnie InputStream, co robię źle?
Tyler Collier,
3
Gdybym mógł teraz również ustawić datę wygaśnięcia zawartości pamięci podręcznej, moje życie byłoby o wiele łatwiejsze :)
Janusz
11
@Scienceprodigy nie mam pojęcia, czym jest ten BitmapLoader, z pewnością nie ma go w żadnej standardowej bibliotece Androida, którą znam, ale przynajmniej poprowadziło mnie to we właściwym kierunku. Bitmap response = BitmapFactory.decodeStream((InputStream)connection.getContent());
Stephen Fuhry
6
Pamiętaj, aby zapoznać się z odpowiedzią Joe poniżej na temat dodatkowych kroków, które musisz wykonać, aby pamięć podręczna działała
Keith
65

Odnośnie eleganckiego connection.setUseCachesrozwiązania powyżej: niestety nie zadziała bez dodatkowego wysiłku. Będziesz musiał zainstalować ResponseCacheusing ResponseCache.setDefault. W przeciwnym razie HttpURLConnectionpo cichu zignoruje setUseCaches(true)bit.

Aby FileResponseCache.javauzyskać szczegółowe informacje, zobacz komentarze u góry :

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

(Opublikowałbym to w komentarzu, ale najwyraźniej nie mam wystarczająco dużo karmy SOJ).

Joe
źródło
Oto plik
Telémako,
2
Kiedy używasz an HttpResponseCache, możesz znaleźć HttpResponseCache.getHitCount()zwracające 0. Nie jestem pewien, ale myślę, że dzieje się tak, ponieważ żądany serwer WWW nie używa w tym przypadku nagłówków pamięci podręcznej. Aby mimo wszystko buforowanie działało, użyj connection.addRequestProperty("Cache-Control", "max-stale=" + MAX_STALE_CACHE);.
Almer
1
Link do wyszukiwania kodów Google jest martwy (znowu?), Zaktualizuj łącze.
Felix D.
Nie jestem też pewien, czy to zachowanie zostało już naprawione. Z jakiegoś powodu zwrócenie 304 z serwera spowodowałoby zawieszenie HUC podczas korzystania z .getContent()metody, ponieważ odpowiedzi 304 nie mają powiązanej treści odpowiedzi według standardu RFC.
TheRealChx101,
27

Przekonwertuj je na mapy bitowe, a następnie zapisz je w kolekcji (mapa haszowania, lista itp.) Lub możesz zapisać je na karcie SD.

Przechowując je w przestrzeni aplikacji przy użyciu pierwszego podejścia, możesz chcieć owinąć je wokół java.lang.ref.SoftReference, szczególnie jeśli ich liczba jest duża (aby były zbierane jako śmieci podczas kryzysu). Może to jednak spowodować przeładowanie.

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

zapisanie ich na karcie SD nie będzie wymagało ponownego załadowania; tylko zezwolenie użytkownika.

Samuh
źródło
jak możemy zapisać obraz na SD lub w pamięci telefonu?
d-man
Aby zapisać obrazy na karcie SD: Możesz zapisać strumienie obrazów odczytane ze zdalnego serwera do pamięci przy użyciu normalnych operacji we / wy na plikach lub, jeśli przekonwertowałeś swoje obrazy na obiekty bitmapowe, możesz użyć metody Bitmap.compress ().
Samuh
@ d-man Sugerowałbym najpierw napisanie na dysk, a następnie uzyskanie Uriodniesienia do ścieżki, do którego można przejść, ImageViewi innych niestandardowych widoków. Ponieważ za każdym razem compressbędziesz tracić jakość. Oczywiście dotyczy to tylko algorytmów stratnych. Ta metoda umożliwiłaby nawet przechowywanie skrótu pliku i użycie go następnym razem, gdy zażądasz pliku z serwera za pośrednictwem If-None-Matchi ETagnagłówków.
TheRealChx101
@ TheRealChx101 czy mógłbyś pomóc zrozumieć, co masz na myśli następnym razem, gdy zażądasz pliku z serwera za pośrednictwem nagłówków If-None-Match i ETag , zasadniczo szukam rozwiązania, w którym obraz powinien pozostać do użycia z lokalnej pamięci podręcznej dla zdefiniowanych okres LUB jeśli nie można tego osiągnąć, wówczas za każdym razem, gdy zmienia się zawartość adresu URL, powinno to odzwierciedlać w aplikacji najnowszą i zapisywać ją w pamięci podręcznej.
CoDe
@CoDe Odwiedź teraz ten link, android.jlelse.eu/ ...
TheRealChx101
27

Służy LruCachedo wydajnego buforowania obrazów. Można przeczytać o LruCachez Android Developer miejscu

Użyłem poniższego rozwiązania do pobierania i buforowania obrazów w systemie Android. Możesz wykonać poniższe czynności:

KROK 1: nadaj klasie nazwę ImagesCache. UżyłemSingleton 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();
        }       
    }

}

KROK 2:

stwórz kolejną klasę o nazwie DownloadImageTask, która jest używana, jeśli bitmapa nie jest dostępna w pamięci podręcznej, pobierze ją stąd:

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;
    }

KROK 3: Użycie z Twojego ActivitylubAdapter

Uwaga: jeśli chcesz załadować obraz z adresu URL z ActivityClass. Użyj drugiego Konstruktora z DownloadImageTask, ale jeśli chcesz wyświetlić obraz z Adapterużyj pierwszego Konstruktora z DownloadImageTask(na przykład masz obraz w ListViewi ustawiasz obraz z 'Adaptera')

WYKORZYSTANIE Z AKTYWNOŚCI:

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);
}

UŻYCIE Z ADAPTERA:

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);
}

Uwaga:

cache.initializeCache()możesz użyć tego stwierdzenia w pierwszym działaniu swojej aplikacji. Po zainicjowaniu pamięci podręcznej nigdy nie będziesz musiał jej inicjować za każdym razem, jeśli używasz ImagesCacheinstancji.

Nigdy nie jestem dobry w wyjaśnianiu rzeczy, ale mam nadzieję, że pomoże to początkującym, jak buforować użycie LruCachei jego użycie :)

EDYTOWAĆ:

Obecnie istnieją bardzo znane biblioteki znane jako Picassoi, Glidektóre mogą być używane do bardzo wydajnego ładowania obrazów w aplikacji na Androida. Wypróbuj tę bardzo prostą i użyteczną bibliotekę Picasso na Androida i Glide na Androida . Nie musisz martwić się o obrazy w pamięci podręcznej.

Picasso umożliwia bezproblemowe ładowanie obrazu w Twojej aplikacji - często w jednej linii kodu!

Glide, podobnie jak Picasso, może ładować i wyświetlać obrazy z wielu źródeł, jednocześnie dbając o buforowanie i zachowując niewielki wpływ na pamięć podczas wykonywania manipulacji obrazami. Był używany przez oficjalne aplikacje Google (jak aplikacja na Google I / O 2015) i jest tak samo popularny jak Picasso. W tej serii przyjrzymy się różnicom i zaletom Glide nad Picassem.

Możesz również odwiedzić blog, aby zobaczyć różnicę między Glide i Picasso

Zubair Ahmed
źródło
3
Znakomita odpowiedź i wyjaśnienie! Myślę, że to najlepsze rozwiązanie, ponieważ działa w trybie offline i korzysta z Androida LruCache. Odkryłem, że rozwiązanie edrowland nie działa w trybie samolotowym, nawet z dodatkiem Joe, który wymagał więcej wysiłku, aby go zintegrować. Btw, wygląda na to, że Android lub sieć zapewniają znaczną ilość pamięci podręcznej, nawet jeśli nie robisz nic więcej. (Jedna drobna uwaga: w przypadku użycia próbki getImageFromWareHouse, litera „H” powinna być zapisana małą literą). Dzięki!
Edwin Evans,
1
świetne wyjaśnienie :)
XtreemDeveloper
Czy mógłbyś wyjaśnić metodę getImage (), w szczególności co robi z rozmiarem obrazu i jak to się dzieje. Nie rozumiem na przykład, dlaczego ponownie wywołujesz funkcję wewnątrz siebie i jak ona działa.
Greyshack
1
Głosuj za tym, if(cache == null)co rozwiązało mój problem! :)
MR. Garcia
1
Zobacz także moją redagowaną odpowiedź na końcu. Wspominałem o znanych bibliotekach używanych przez większość programistów od kilku dni. Wypróbuj te Picassa: square.github.io/picasso i Glide: futurestud.io/blog/glide-getting-started
Zubair Ahmed
18

Aby pobrać obraz i zapisać na karcie pamięci, możesz to zrobić w ten sposób.

//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));

Nie zapomnij dodać pozwolenia internetowego do swojego manifestu:

<uses-permission android:name="android.permission.INTERNET" />
Ljdawson
źródło
10
Dlaczego dekodujesz plik JPEG, a następnie ponownie go kodujesz? Lepiej jest pobrać adres URL do tablicy bajtów, a następnie użyć tej tablicy bajtów do utworzenia mapy bitowej i zapisania do pliku. Za każdym razem, gdy dekodujesz i ponownie kodujesz JPEG, jakość obrazu pogarsza się.
CommonsWare
2
Słuszna uwaga, bardziej chodziło o szybkość niż cokolwiek. Chociaż gdyby zapisano jako tablicę bajtów, a plik źródłowy nie był plikiem JPEG, czy plik i tak nie musiałby być konwertowany? „decodeByteArray” z zestawu SDK zwraca „Zdekodowana mapa bitowa lub wartość zerowa, jeśli dane obrazu nie mogą zostać zdekodowane”, więc wydaje mi się, że zawsze dekoduje dane obrazu, więc czy nie wymagałoby to ponownego kodowania?
Ljdawson
Mówiąc o wydajności, czy nie byłoby wydajne, gdybyśmy zamiast przekazywania FileOutputStream przekazali BufferedOutputStream?
Samuh
1
nie sugeruję buforowania obrazów na karcie SD. po odinstalowaniu aplikacji obrazy nie są usuwane, powodując zapełnienie karty SD bezużytecznymi śmieciami. preferowane jest zapisywanie obrazów w katalogu pamięci podręcznej aplikacji. IMO
james
Przy obecnym limicie APK wynoszącym 50 MB buforowanie na karcie SD może być jedynym sposobem dla programistów.
Ljdawson
13

Rozważałbym użycie pamięci podręcznej obrazu droidfu. Implementuje zarówno pamięć podręczną obrazów w pamięci, jak i na dysku. Otrzymujesz również WebImageView, który korzysta z biblioteki ImageCache.

Oto pełny opis droidfu i WebImageView: http://brainflush.wordpress.com/2009/11/23/droid-fu-part-2-webimageview-and-webgalleryadapter/

esilver
źródło
Refaktoryzuje swój kod od 2010 roku; tutaj jest link główny: github.com/kaeppler/droid-fu
esilver
3
Ten link nadal nie działa. Napisałem podobną bibliotekę o nazwie Android-ImageManager github.com/felipecsl/Android-ImageManager
Felipe Lima
9

Wypróbowałem SoftReferences, są zbyt agresywnie odzyskiwane w Androidzie, że czułem, że nie ma sensu ich używać

2cupsOfTech
źródło
2
Zgoda - SoftReferences jest bardzo szybko odzyskiwana na testowanych
przeze
3
Google samo potwierdziło, że GC Dalvik jest bardzo agresywny w zbieraniu SoftReferenceplików. Zalecają używanie ich LruCachezamiast tego.
kaka
9

Jak zasugerował Thunder Rabbit, ImageDownloader jest najlepszy do tego zadania. Znalazłem też niewielkie zróżnicowanie klasy na:

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

Główna różnica między nimi polega na tym, że ImageDownloader używa systemu pamięci podręcznej Androida, a zmodyfikowany wykorzystuje pamięć wewnętrzną i zewnętrzną jako buforowanie, przechowując obrazy w pamięci podręcznej przez czas nieokreślony lub do momentu, gdy użytkownik usunie je ręcznie. Autor wspomina również o kompatybilności z Androidem 2.1.

EZFrag
źródło
7

To dobry chwyt Joe. Powyższy przykład kodu ma dwa problemy - jeden - obiekt odpowiedzi nie jest instancją Bitmap (kiedy mój adres URL odwołuje się do pliku jpg, np. Http: \ website.com \ image.jpg, jest to plik a

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

Po drugie, jak wskazuje Joe, żadne buforowanie nie występuje bez skonfigurowania pamięci podręcznej odpowiedzi. Deweloperzy Androida są zmuszeni do rozwijania własnej pamięci podręcznej. Oto przykład, jak to zrobić, ale buforuje tylko w pamięci, co tak naprawdę nie jest pełnym rozwiązaniem.

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

Interfejs API buforowania URLConnection opisano tutaj:

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

Nadal uważam, że jest to dobre rozwiązanie, aby przejść tę trasę - ale nadal musisz napisać pamięć podręczną. Brzmi fajnie, ale wolałbym pisać funkcje.

Peter Pascale
źródło
7

W oficjalnej sekcji szkoleniowej Androida jest na ten temat specjalny wpis: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

Sekcja jest całkiem nowa, nie było jej tam, kiedy zadano pytanie.

Sugerowanym rozwiązaniem jest użycie LruCache. Ta klasa została wprowadzona w Honeycomb, ale jest również uwzględniona w bibliotece zgodności.

Możesz zainicjować LruCache, ustawiając maksymalną liczbę lub wpisy, a on automatycznie posortuje je według Ciebie i wyczyści rzadziej używane, gdy przekroczysz limit. Poza tym jest używana jako normalna mapa.

Przykładowy kod z oficjalnej strony:

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);
}

Wcześniej SoftReferences były dobrą alternatywą, ale już nie, cytując z oficjalnej strony:

Uwaga: W przeszłości popularną implementacją pamięci podręcznej była pamięć podręczna mapy bitowej SoftReference lub WeakReference, jednak nie jest to zalecane. Począwszy od Androida 2.3 (poziom API 9), moduł odśmiecania pamięci jest bardziej agresywny w zbieraniu miękkich / słabych odniesień, co czyni je dość nieefektywnymi. Ponadto przed Androidem 3.0 (poziom interfejsu API 11) dane kopii zapasowej mapy bitowej były przechowywane w pamięci natywnej, która nie jest udostępniana w przewidywalny sposób, co może powodować krótkotrwałe przekroczenie limitów pamięci i awarię aplikacji.

shalafi
źródło
3

Rozważ użycie biblioteki Universal Image Loader autorstwa Sergeya Tarasevicha . Pochodzi z:

  • Ładowanie obrazu wielowątkowego. Pozwala zdefiniować rozmiar puli wątków
  • Buforowanie obrazu w pamięci, w systemie plików urządzenia i na karcie SD.
  • Możliwość odsłuchania postępu ładowania i zdarzeń ładowania

Universal Image Loader umożliwia szczegółowe zarządzanie pamięcią podręczną pobranych obrazów z następującymi konfiguracjami pamięci podręcznej:

  • UsingFreqLimitedMemoryCache: Najrzadziej używana mapa bitowa jest usuwana po przekroczeniu limitu rozmiaru pamięci podręcznej.
  • LRULimitedMemoryCache: Najmniej używana mapa bitowa jest usuwana po przekroczeniu limitu rozmiaru pamięci podręcznej.
  • FIFOLimitedMemoryCache: Reguła FIFO jest używana do usuwania, gdy zostanie przekroczony limit rozmiaru pamięci podręcznej.
  • LargestLimitedMemoryCache: Największa mapa bitowa jest usuwana po przekroczeniu limitu rozmiaru pamięci podręcznej.
  • LimitedAgeMemoryCache: Obiekt w pamięci podręcznej jest usuwany, gdy jego wiek przekroczy zdefiniowaną wartość .
  • WeakMemoryCache: Pamięć podręczna zawierająca tylko słabe odniesienia do map bitowych.

Prosty przykład użycia:

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);

W tym przykładzie użyto domyślnej UsingFreqLimitedMemoryCache.

Gunnar Karlsson
źródło
Przy intensywnym użytkowaniu Universal Image Loader spowoduje wiele wycieków pamięci. Podejrzewam, że dzieje się tak, ponieważ używa w kodzie singletonów (patrz „getInstance ()” w przykładzie). Po załadowaniu wielu obrazów, a następnie kilkukrotnym obróceniu ekranu, moja aplikacja cały czas ulegała awarii z powodu błędów OutOfMemoryErrors w UIL. To świetna biblioteka, ale to dobrze znany fakt, że NIGDY nie powinieneś używać singletonów, zwłaszcza w Androidzie ...
Geert Bellemans.
1
UŻYWAJ singletonów, kiedy wiesz jak! :)
Renetik
3

To, co faktycznie zadziałało, to ustawienie ResponseCache w mojej klasie głównej:

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

i

connection.setUseCaches(true);

podczas pobierania mapy bitowej.

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

ZamPrano
źródło
czy można używać lrucache w połączeniu z httpresponsecache
iOSAndroidWindowsMobileAppsDev
1

Zmagałem się z tym przez jakiś czas; odpowiedzi za pomocą SoftReferences zbyt szybko utraciłyby dane. Odpowiedzi, które sugerują utworzenie wystąpienia RequestCache, były zbyt skomplikowane, a ponadto nigdy nie mogłem znaleźć pełnego przykładu.

Ale ImageDownloader.java działa wspaniale dla mnie. Używa HashMap do momentu osiągnięcia pojemności lub do upływu limitu czasu oczyszczania, a następnie przenosi rzeczy do SoftReference, wykorzystując w ten sposób to, co najlepsze z obu światów.

Thunder Rabbit
źródło
0

Jeszcze później odpowiedź, ale napisałem Menedżera obrazów Androida, który obsługuje buforowanie w sposób przezroczysty (pamięć i dysk). Kod znajduje się na Github https://github.com/felipecsl/Android-ImageManager

Felipe Lima
źródło
1
Dodałem to do ListView i wydaje się, że nie radzi sobie z tym zbyt dobrze. Czy istnieje jakaś specjalna implementacja ListViews?
0

Późne odpowiedź, ale pomyślałem, powinienem dodać link do mojej strony, bo pisałem tutorial jak zrobić bufor obrazu dla android: http://squarewolf.nl/2010/11/android-image-cache/ Aktualizacja: strona została przeniesiona do trybu offline, ponieważ jej źródło było nieaktualne. Dołączam do @elenasys w jej radach dotyczących używania Ignition .

A więc do wszystkich ludzi, którzy natknęli się na to pytanie i nie znaleźli rozwiązania: mam nadzieję, że Ci się spodoba! = D

Thomas Vervest
źródło
0

Późna odpowiedź, ale myślę, że ta biblioteka bardzo pomoże w buforowaniu obrazów: https://github.com/crypticminds/ColdStorage .

Po prostu dodaj adnotację ImageView za pomocą @LoadCache (R.id.id_of_my_image_view, "URL_to_downlaod_image_from), a zajmie się pobieraniem obrazu i ładowaniem go do widoku obrazu. Możesz również określić obraz zastępczy i załadować animację.

Szczegółowa dokumentacja adnotacji znajduje się tutaj: - https://github.com/crypticminds/ColdStorage/wiki/@LoadImage-annotation

Anurag Mandal
źródło