Como posso armazenar em cache imagens depois que elas são baixadas da Web?
141
E agora a dica: use o cache do sistema.
URL url = new URL(strUrl);
URLConnection connection = url.openConnection();
connection.setUseCaches(true);
Object response = connection.getContent();
if (response instanceof Bitmap) {
Bitmap bitmap = (Bitmap)response;
}
Fornece memória e cache flash-rom, compartilhados com o navegador.
grr. Eu gostaria que alguém tivesse me dito isso antes de escrever meu próprio gerenciador de cache.
connection.getContent()
sempre retorna um InputStream para mim, o que estou fazendo de errado?Bitmap response = BitmapFactory.decodeStream((InputStream)connection.getContent());
Em relação à
connection.setUseCaches
solução elegante acima: infelizmente, ela não funcionará sem um esforço adicional. Você precisará instalar umResponseCache
usandoResponseCache.setDefault
. Caso contrário,HttpURLConnection
silenciosamente ignorará osetUseCaches(true)
bit.Veja os comentários no topo de
FileResponseCache.java
para detalhes:http://libs-for-android.googlecode.com/svn/reference/com/google/android/filecache/FileResponseCache.html
(Eu publicaria isso em um comentário, mas aparentemente não tenho karma SO suficiente.)
fonte
HttpResponseCache
, você pode encontrar oHttpResponseCache.getHitCount()
0. retornado. Não tenho certeza, mas acho que é porque o servidor da web que você está solicitando não usa cabeçalhos de cache nesse caso. Para fazer o cache funcionar de qualquer maneira, useconnection.addRequestProperty("Cache-Control", "max-stale=" + MAX_STALE_CACHE);
..getContent()
método, porque as respostas 304 não têm um corpo de resposta associado pelo padrão RFC.Converta-os em bitmaps e, em seguida, armazene-os em uma coleção (HashMap, lista etc.) ou escreva-os no cartão SD.
Ao armazená-los no espaço do aplicativo usando a primeira abordagem, convém agrupá-los em torno de um java.lang.ref.SoftReference especificamente se seus números forem grandes (para que eles sejam coletados durante a crise). Isso poderia resultar em uma recarga.
escrevê-los no cartão SD não exigirá uma recarga; apenas uma permissão do usuário.
fonte
Uri
referência de caminho para a qual você possa passarImageView
e outras visualizações personalizadas. Porque cada vez quecompress
você perde qualidade. Claro que isso é verdade apenas para algoritmos com perdas. Esse método também permite armazenar um hash do arquivo e usá-lo na próxima vez que você solicitar o arquivo do servidor através deIf-None-Match
eETag
cabeçalhos.Use
LruCache
para armazenar em cache imagens com eficiência. Você pode ler sobreLruCache
no site do desenvolvedor do AndroidEu usei abaixo solução para imagens baixar e cache no android. Você pode seguir as etapas abaixo:
PASSO 1: torne a classe nomeada
ImagesCache
. Eu useiSingleton object for this class
PASSO 2:
faça outra classe chamada DownloadImageTask que é usada se o bitmap não estiver disponível no cache, ele fará o download aqui:
PASSO 3: Uso do seu
Activity
ouAdapter
Nota: Se você deseja carregar a imagem do URL da
Activity
Classe. Use o segundo Construtor deDownloadImageTask
, mas se você deseja exibir uma imagem,Adapter
use o primeiro Construtor deDownloadImageTask
(por exemplo, você tem uma imagemListView
e está definindo a imagem em 'Adaptador')USO DA ATIVIDADE:
USO DO ADAPTADOR:
Nota:
cache.initializeCache()
você pode usar esta declaração na primeira atividade do seu aplicativo. Depois de inicializar o cache, você nunca precisará inicializá-lo todas as vezes se estiver usando umaImagesCache
instância.Eu nunca sou bom em explicar as coisas, mas espero que isso ajude os iniciantes a como usar o cache
LruCache
e seu uso :)EDITAR:
Hoje em dia, existem bibliotecas muito famosas conhecidas como
Picasso
eGlide
que podem ser usadas para carregar imagens com muita eficiência no aplicativo Android. Experimente esta biblioteca Picasso muito simples e útil para Android e Glide For Android . Você não precisa se preocupar com imagens de cache.Você também pode visitar o blog para saber a diferença entre Glide e Picasso
fonte
if(cache == null)
que resolveu meu problema! :)Para baixar uma imagem e salvar no cartão de memória, você pode fazer o seguinte.
Não se esqueça de adicionar a permissão da Internet ao seu manifesto:
fonte
Eu consideraria usar o cache de imagem do droidfu. Ele implementa um cache de imagem na memória e baseado em disco. Você também recebe um WebImageView que tira proveito da biblioteca ImageCache.
Aqui está a descrição completa do droidfu e do WebImageView: http://brainflush.wordpress.com/2009/11/23/droid-fu-part-2-webimageview-and-webgalleryadapter/
fonte
Eu tentei o SoftReferences, eles são recuperados de forma muito agressiva no Android e eu senti que não havia sentido em usá-los
fonte
SoftReference
s. Eles recomendam o uso delesLruCache
.Como o Thunder Rabbit sugeriu, o ImageDownloader é o melhor para o trabalho. Também encontrei uma pequena variação da classe em:
http://theandroidcoder.com/utilities/android-image-download-and-caching/
A principal diferença entre os dois é que o ImageDownloader usa o sistema de cache do Android e o modificado usa armazenamento interno e externo como cache, mantendo as imagens em cache indefinidamente ou até que o usuário as remova manualmente. O autor também menciona a compatibilidade com o Android 2.1.
fonte
Essa é uma boa notícia para Joe. O exemplo de código acima tem dois problemas - um - o objeto de resposta não é uma instância do Bitmap (quando meu URL faz referência a um jpg, como http: \ website.com \ image.jpg, é um
org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl $ LimitedInputStream).
Segundo, como Joe ressalta, nenhum cache ocorre sem que um cache de resposta esteja configurado. Os desenvolvedores do Android têm que rolar seu próprio cache. Aqui está um exemplo para fazer isso, mas ele apenas armazena em cache a memória, o que realmente não é a solução completa.
http://codebycoffee.com/2010/06/29/using-responsecache-in-an-android-app/
A API de armazenamento em cache do URLConnection é descrita aqui:
http://download.oracle.com/javase/6/docs/technotes/guides/net/http-cache.html
Ainda acho que essa é uma solução boa para seguir esse caminho - mas você ainda precisa escrever um cache. Parece divertido, mas eu prefiro escrever recursos.
fonte
Há uma entrada especial na seção de treinamento oficial do Android sobre isso: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
A seção é bastante nova, não estava lá quando a pergunta foi feita.
A solução sugerida é usar um LruCache. Essa classe foi introduzida no Honeycomb, mas também está incluída na biblioteca de compatibilidade.
Você pode inicializar um LruCache configurando o número máximo ou entradas e ele automaticamente os classifica como você e os limpa menos usados quando você ultrapassa o limite. Fora isso, ele é usado como um mapa normal.
O código de amostra da página oficial:
Anteriormente, as SoftReferences eram uma boa alternativa, mas não mais, citando a partir da página oficial:
fonte
Considere usar a biblioteca Universal Image Loader de Sergey Tarasevich . Vem com:
O Universal Image Loader permite gerenciamento detalhado de cache para imagens baixadas, com as seguintes configurações de cache:
UsingFreqLimitedMemoryCache
: O bitmap usado com menos frequência é excluído quando o limite de tamanho do cache é excedido.LRULimitedMemoryCache
: O bitmap usado menos recentemente é excluído quando o limite de tamanho do cache é excedido.FIFOLimitedMemoryCache
: A regra FIFO é usada para exclusão quando o limite de tamanho do cache é excedido.LargestLimitedMemoryCache
: O maior bitmap é excluído quando o limite de tamanho do cache é excedido.LimitedAgeMemoryCache
: O objeto em cache é excluído quando sua idade excede o valor definido .WeakMemoryCache
: Um cache de memória com apenas referências fracas a bitmaps.Um exemplo simples de uso:
Este exemplo usa o padrão
UsingFreqLimitedMemoryCache
.fonte
O que realmente funcionou para mim foi definir o ResponseCache na minha classe Principal:
e
ao baixar bitmap.
http://practicaldroid.blogspot.com/2013/01/utilizing-http-response-cache.html
fonte
O libs-for-android do Google possui ótimas bibliotecas para gerenciar o cache de imagens e arquivos.
http://code.google.com/p/libs-for-android/
fonte
Eu estava lutando com isso há algum tempo; as respostas usando o SoftReferences perderiam seus dados muito rapidamente. As respostas que sugerem instanciar um RequestCache eram muito complicadas, e eu nunca consegui encontrar um exemplo completo.
Mas ImageDownloader.java funciona maravilhosamente para mim. Ele usa um HashMap até que a capacidade seja atingida ou até que o tempo limite da limpeza ocorra, depois as coisas são movidas para um SoftReference, usando assim o melhor dos dois mundos.
fonte
Eu sugiro que a IGNIÇÃO seja ainda melhor do que o Droid fu
https://github.com/kaeppler/ignition
https://github.com/kaeppler/ignition/wiki/Sample-applications
fonte
Resposta ainda mais tarde, mas escrevi um Android Image Manager que lida com o cache de forma transparente (memória e disco). O código está no Github https://github.com/felipecsl/Android-ImageManager
fonte
Resposta tardia, mas achei que deveria adicionar um link ao meu site porque escrevi um tutorial sobre como fazer um cache de imagens para o Android:
http://squarewolf.nl/2010/11/android-image-cache/Update: the A página foi colocada offline porque a fonte estava desatualizada. Associo-me à @ elenasys nos conselhos dela para usar o Ignition .Portanto, para todas as pessoas que se deparam com essa pergunta e não encontraram uma solução: espero que gostem! = D
fonte
Resposta tardia, mas acho que esta biblioteca ajudará muito no armazenamento de imagens em cache: https://github.com/crypticminds/ColdStorage .
Basta anotar o ImageView com @LoadCache (R.id.id_of_my_image_view, "URL_to_downlaod_image_from) e ele cuidará do download da imagem e do carregamento na visualização da imagem. Também é possível especificar uma imagem de espaço reservado e carregar a animação.
A documentação detalhada da anotação está presente aqui: - https://github.com/crypticminds/ColdStorage/wiki/@LoadImage-annotation
fonte