Yanıtlar:
Ve şimdi yumruk çizgisi: sistem önbelleğini kullanın.
URL url = new URL(strUrl);
URLConnection connection = url.openConnection();
connection.setUseCaches(true);
Object response = connection.getContent();
if (response instanceof Bitmap) {
Bitmap bitmap = (Bitmap)response;
}
Tarayıcı ile paylaşılan hem bellek hem de flash-rom önbellek sağlar.
grr. Birisi bana kendi önbellek yöneticimi yazmadan önce söylemiş olsaydı.
connection.getContent()
benim için her zaman bir InputStream döndürür, ne yanlış yapıyorum?
Bitmap response = BitmapFactory.decodeStream((InputStream)connection.getContent());
connection.setUseCaches
Yukarıdaki zarif çözümle ilgili olarak : ne yazık ki, ek çaba harcamadan çalışmayacaktır. ResponseCache
Kullanarak yüklemeniz gerekecektir ResponseCache.setDefault
. Aksi takdirde, ucu HttpURLConnection
sessizce göz ardı eder setUseCaches(true)
.
Ayrıntılar için sayfanın üst kısmındaki yorumlara FileResponseCache.java
bakın:
(Bunu bir yorumda yayınlarım ama görünüşe göre yeterince SO karmam yok.)
HttpResponseCache
, HttpResponseCache.getHitCount()
dönen 0'ı bulabilirsiniz. Emin değilim ama bence bu talep ettiğiniz web sunucusu bu durumda önbellek başlıklarını kullanmıyor. Önbelleğe alma işlemini yine de yapmak için kullanın connection.addRequestProperty("Cache-Control", "max-stale=" + MAX_STALE_CACHE);
.
.getContent()
304 yanıtın RFC standardına göre ilişkili bir yanıt gövdesi olmadığından , sunucudan 304 döndürüldüğünde HUC askıda kalır .
Bunları Bitmap'lere dönüştürün ve sonra bunları bir Koleksiyonda (HashMap, List vb.) Saklayın veya SD karta yazabilirsiniz.
Bunları ilk yaklaşımı kullanarak uygulama alanında saklarken, özellikle java.lang.ref.SoftReference çevresine sarmak isteyebilirsiniz, özellikle de sayıları büyükse (kriz sırasında toplanan çöplerdir). Bu yine de yeniden yükleme yapabilir.
HashMap<String,SoftReference<Bitmap>> imageCache =
new HashMap<String,SoftReference<Bitmap>>();
SD karta yazmak için Yeniden Yükleme gerekmez; sadece bir kullanıcı izni.
Uri
geçebileceğiniz bir yol başvurusu ImageView
ve diğer özel görünümleri almanızı öneririm . Çünkü her seferinde compress
kalitenizi kaybedeceksiniz. Tabii ki bu sadece kayıplı algoritmalar için geçerlidir. Bu yöntem ayrıca dosyanın bir karmasını depolamanıza ve dosyayı sunucudan If-None-Match
ve ETag
üstbilgilerden bir sonraki istekte bulunduğunuzda kullanmanıza izin verir .
LruCache
Görüntüleri verimli bir şekilde önbelleğe almak için kullanın . Android Geliştirici sitesinden hakkında bilgi LruCache
edinebilirsiniz
Android'de Görüntüler indirmek ve önbelleğe almak için aşağıdaki çözümü kullandım. Aşağıdaki adımları takip edebilirsiniz:
ADIM 1:
Sınıfı adlandırın ImagesCache
. KullandımSingleton 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();
}
}
}
ADIM 2:
Bitmap önbellekte yoksa, DownloadImageTask adında başka bir sınıf yapın, buradan indirebilirsiniz:
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;
}
ADIM 3: dan Kullanımı senin Activity
yaAdapter
Not:Activity
Class'tan url'den resim yüklemek istiyorsanız . İkinci Yapıcı'yı kullanın DownloadImageTask
, ancak görüntüyü Adapter
ilk Kullanımdan görüntülemek istiyorsanız DownloadImageTask
(örneğin, içinde bir görüntünüz var ListView
ve 'Bağdaştırıcı'dan bir görüntü ayarlıyorsunuz)
AKTİVİTEDEN KULLANIM:
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);
}
ADAPTÖRDEN KULLANIM:
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);
}
Not:
cache.initializeCache()
bu ifadeyi başvurunuzun ilk Etkinliğinde kullanabilirsiniz. Önbelleği başlattıktan sonra, her kullandığınızda asla başlatmanız gerekmez.ImagesCache
örnek .
Hiçbir şeyi açıklama konusunda asla iyi değilim ama umarım bu yeni başlayanlara kullanarak önbellek kullanmayı LruCache
kullanımı ve kullanımı :)
DÜZENLE:
Şimdi bir gün olarak bilinen Picasso
ve Glide
android uygulamasında görüntüleri çok verimli bir şekilde yüklemek için kullanılabilecek çok ünlü kütüphaneler var . Bu çok basit ve kullanışlı bir kütüphane deneyin android için Picasso ve Glide için Android . Önbellek görüntüleri hakkında endişelenmenize gerek yoktur.
Picasso, uygulamanızda sorunsuz bir şekilde resim yüklemeye olanak tanır - genellikle tek bir kod satırında!
Glide, tıpkı Picasso gibi, birçok kaynaktan gelen görüntüleri yükleyebilir ve görüntüleyebilir, aynı zamanda önbelleğe almayı ve görüntü manipülasyonları yaparken düşük bellek etkisini koruyabilir. Resmi Google uygulamaları tarafından (Google I / O 2015 uygulaması gibi) kullanılmıştır ve Picasso kadar popülerdir. Bu dizide Glide'ın Picasso'ya göre farklılıklarını ve avantajlarını keşfedeceğiz.
Glide ve Picasso arasındaki fark için blog'u da ziyaret edebilirsiniz.
if(cache == null)
! :)
Bir görüntüyü indirmek ve hafıza kartına kaydetmek için bunu böyle yapabilirsiniz.
//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));
Manifestinize İnternet izni eklemeyi unutmayın:
<uses-permission android:name="android.permission.INTERNET" />
Droidfu'nun görüntü önbelleğini kullanmayı düşünürdüm. Hem bellek içi hem de disk tabanlı görüntü önbelleği uygular. Ayrıca ImageCache kütüphanesinden yararlanan bir WebImageView elde edersiniz.
Droidfu ve WebImageView tam açıklaması: http://brainflush.wordpress.com/2009/11/23/droid-fu-part-2-webimageview-and-webgalleryadapter/
SoftReferences denedim, onlar çok agresif android onları kullanarak hiçbir anlamı olduğunu hissettim geri talep
SoftReference
. Onların LruCache
yerine kullanmanızı öneririz .
Thunder Rabbit'in önerdiği gibi, ImageDownloader iş için en iyisidir. Ayrıca sınıfın hafif bir varyasyonunu da buldum:
http://theandroidcoder.com/utilities/android-image-download-and-caching/
İkisi arasındaki temel fark, ImageDownloader'ın Android önbellek sistemini kullanması ve değiştirilmiş olanın önbellek olarak dahili ve harici depolamayı kullanması, önbelleğe alınmış görüntüleri süresiz olarak veya kullanıcı manuel olarak kaldırana kadar tutmasıdır. Yazar ayrıca Android 2.1 uyumluluğundan bahsediyor.
Bu Joe tarafından iyi bir yakalama. Yukarıdaki kod örneğinde iki sorun vardır - bir - yanıt nesnesi bir Bitmap örneği değildir (URL'm http: \ website.com \ image.jpg gibi bir jpg'ye başvurduğunda,
org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl $ LimitedInputStream).
İkincisi, Joe'nun işaret ettiği gibi, bir yanıt önbelleği yapılandırılmadan hiçbir önbellekleme gerçekleşmez. Android geliştiricileri kendi önbelleklerini kullanmaya başladılar. İşte bunu yapmak için bir örnek, ama sadece bellekte önbellekler, ki bu tam çözüm değil.
http://codebycoffee.com/2010/06/29/using-responsecache-in-an-android-app/
URLConnection önbellek API'si burada açıklanmaktadır:
http://download.oracle.com/javase/6/docs/technotes/guides/net/http-cache.html
Hala bu rotaya gitmek için iyi bir çözüm olduğunu düşünüyorum - ama yine de bir önbellek yazmanız gerekiyor. Kulağa eğlenceli geliyor ama özellikleri yazmayı tercih ederim.
Android'in resmi eğitim bölümünde bununla ilgili özel bir giriş var: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
Bölüm oldukça yeni, soru sorulduğunda orada değildi.
Önerilen çözüm bir LruCache kullanmaktır. Bu sınıf Honeycomb'da tanıtıldı, ancak uyumluluk kitaplığına da dahil edildi.
Maksimum sayı veya girişleri ayarlayarak bir LruCache'i başlatabilirsiniz ve sınırın üzerine çıktığınızda bunları otomatik olarak sıralar ve daha az kullanılanları temizler. Bunun dışında normal Harita olarak kullanılır.
Resmi sayfadaki örnek kod:
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);
}
Önceden SoftReferences iyi bir alternatifti, ancak artık resmi sayfadan alıntı yapmadı:
Not: Geçmişte, popüler bir bellek önbellek uygulaması bir SoftReference veya WeakReference bitmap önbelleğiydi, ancak bu önerilmez. Android 2.3'ten (API Seviye 9) başlayarak, çöp toplayıcı yumuşak / zayıf referansları toplama konusunda daha agresiftir ve bu da onları oldukça etkisiz hale getirir. Ek olarak, Android 3.0'dan (API Seviye 11) önce, bir bitmap'in yedekleme verileri, öngörülebilir bir şekilde serbest bırakılmayan, potansiyel olarak bir uygulamanın bellek sınırlarını ve çökmesini kısa bir süre aşmasına neden olan yerel bellekte saklandı.
Kullanmayı düşünün Evrensel Görüntü Yükleyici kütüphanesi tarafından Sergey Tarasevich . Birlikte gelir:
Universal Image Loader, indirilen görüntüler için aşağıdaki önbellek yapılandırmalarıyla ayrıntılı önbellek yönetimine izin verir :
UsingFreqLimitedMemoryCache
: En az sıklıkla Önbellek boyutu sınırı aşıldığında kullanılan bitmap silinir.LRULimitedMemoryCache
: En yakın zamanda Önbellek boyutu sınırı aşıldığında kullanılan bitmap silinir.FIFOLimitedMemoryCache
: FIFO kuralı, önbellek boyutu sınırı aşıldığında silinmek için kullanılır.LargestLimitedMemoryCache
: En büyük bitmap, önbellek boyutu sınırı aşıldığında silinir.LimitedAgeMemoryCache
: Önbelleğe alınan nesne, yaşı tanımlanan değeri aştığında silinir .WeakMemoryCache
: Bitmap'lere yalnızca zayıf referansları olan bir bellek önbelleği.Basit bir kullanım örneği:
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);
Bu örnek varsayılanı kullanır UsingFreqLimitedMemoryCache
.
Benim için gerçekten işe yarayan şey, Ana sınıfımda ResponseCache ayarlamaktı:
try {
File httpCacheDir = new File(getApplicationContext().getCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize);
} catch (IOException e) { }
ve
connection.setUseCaches(true);
bitmap indirirken.
http://practicaldroid.blogspot.com/2013/01/utilizing-http-response-cache.html
Google'ın android için libs, görüntü ve dosya önbelleğini yönetmek için güzel bir kütüphaneye sahiptir.
Bir süredir bununla güreşiyordum; SoftReferences kullanan yanıtlar verilerini çok hızlı kaybeder. Bir RequestCache örneği oluşturmayı öneren cevaplar çok dağınıktı, ayrıca hiçbir zaman tam bir örnek bulamadım.
Ama ImageDownloader.java benim için harika çalışıyor. Kapasiteye ulaşılana kadar veya temizleme zaman aşımı gerçekleşene kadar bir HashMap kullanır, ardından işler bir SoftReference öğesine taşınır, böylece her iki dünyanın en iyileri kullanılır.
Önerim ateşleme bu Droid fu daha iyidir
https://github.com/kaeppler/ignition
https://github.com/kaeppler/ignition/wiki/Sample-applications
Daha sonra bile cevap verdim, ancak önbelleğe almayı şeffaf bir şekilde işleyen bir Android Image Manager yazdım (bellek ve disk). Kod Github üzerindedir https://github.com/felipecsl/Android-ImageManager
: Geç cevap, ama ben nasıl android için bir resim önbelleği yapmak için bir öğretici yazdım çünkü siteme bir bağlantı eklemek gerektiğini düşündüm http://squarewolf.nl/2010/11/android-image-cache/ Güncelleme: kaynak eski olduğu için sayfa çevrimdışı oldu. Ignition'ı kullanma önerisinde @elenasys'e katıldım .
Yani bu soruya rastlayan ve bir çözüm bulamayan herkese: umarım beğenirsiniz! = D
Geç cevap ama bu kütüphane önbellek görüntüleri ile çok yardımcı olacağını düşünüyorum: https://github.com/crypticminds/ColdStorage .
ImageView'a @LoadCache (R.id.id_of_my_image_view, "URL_to_downlaod_image_from) ile açıklama eklediğinizde, görüntüyü indirip görüntü görünümüne yüklemeyle de ilgilenebilirsiniz.
Ek açıklamanın ayrıntılı dokümanları burada mevcuttur: - https://github.com/crypticminds/ColdStorage/wiki/@LoadImage-annotation