我使用圖像下載邏輯從網頁顯示圖像,我只想在第一時間下載圖像,下次不要從網上下載圖像,因爲第一次下載圖像存儲在高速緩衝存儲器中,所以我從捕捉內存中顯示圖像,如果不在高速緩衝存儲器中退出那個圖像,否則下載不需要從網上下載那個圖像,怎麼可能?如何使用緩衝存儲器進行圖像下載?
感謝朋友。
我使用圖像下載邏輯從網頁顯示圖像,我只想在第一時間下載圖像,下次不要從網上下載圖像,因爲第一次下載圖像存儲在高速緩衝存儲器中,所以我從捕捉內存中顯示圖像,如果不在高速緩衝存儲器中退出那個圖像,否則下載不需要從網上下載那個圖像,怎麼可能?如何使用緩衝存儲器進行圖像下載?
感謝朋友。
我不是一個Android開發人員,但我相信應該有一種方法來寫入本地內存。 I.e寫入目錄。我猜想圖像是以字節數組的形式從網絡返回的,您可以將其保存到本地內存。然後,只要再次需要,您可以將其讀回。
您可以實現用一個Hashtable緩存「的CacheManager」單例類,所以當你下載完成添加到緩存中的對象做cache.put(IMAGEURL,ImageView的)。必須在單例中執行此操作才能在應用程序生命週期中獲得緩存。
如果您不想在這裏重新發明輪子,您可以使用droid-fu的圖像加載內置緩存,也可以深入瞭解cachefu類以瞭解更多信息。特別是,AbstractCache是兩級緩存的良好基礎;在這種情況下,它保持較小的內存緩存,並且如果SD卡可用,它將保持額外的存在。
這裏是圖像緩存類的鏈接。
http://theandroidcoder.com/utilities/android-image-download-and-caching/
這似乎很好地工作,同時支持內存和SD卡緩存
下面的ImageLoader的類來維持高速緩存內存和磁盤存儲到圖像存儲在盤下載後的圖像。
public class MyImageLoader {
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
private static final String DISK_CACHE_SUBDIR = "ImageCache";
private DiskLruImageCache mDiskLruImageCache;
private ExecutorService executorService;
private LruCache<String, Bitmap> mMemoryCache;
private Map<ImageView, String> imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
private int byteCounts;
private int requiredHeight = 100, requiredWidth = 100; // setting default height & width as 100
private final int default_icon = R.drawable.no_image_friend;
CommonMethod mCommonMethod;
public MyImageLoader(Context context) {
executorService = Executors.newFixedThreadPool(2);
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;
mCommonMethod = new CommonMethod(context);
mDiskLruImageCache = new DiskLruImageCache(context, DISK_CACHE_SUBDIR, DISK_CACHE_SIZE, CompressFormat.PNG, 70);
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
byteCounts = bitmap.getRowBytes() * bitmap.getHeight();
return byteCounts;
}
};
}
public void ExecuteLoading(String urlString, ImageView mImageView) {
imageViews.put(mImageView, urlString);
Bitmap bitmap = getBitmapFromMemCache(urlString);
if (bitmap != null){
mImageView.setImageBitmap(bitmap);
}
else {
executorService.submit(new LoadImages(urlString, mImageView));
mImageView.setImageResource(default_icon);
}
}
boolean ImageViewReused(String urlString, ImageView mImageView){
String tag=imageViews.get(mImageView);
if(tag==null || !tag.equals(urlString))
return true;
return false;
}
class LoadImages implements Runnable {
String urlString;
ImageView mImageView;
DisplayImages images;
public LoadImages(String urlString, ImageView mImageView) {
this.urlString = urlString;
this.mImageView = mImageView;
}
public void run() {
if(!ImageViewReused(urlString, mImageView)){
Bitmap bitmap = DownloadFromUrl(urlString);
Bitmap mBitmapMask = mCommonMethod.makeMaskImageCrop(bitmap, R.drawable.image_thumb_mask, R.drawable.image_thumb);
//TODO to mask image then bitmap pass
addBitmapToDiskCache(urlString, mBitmapMask);
DisplayImages images = new DisplayImages(urlString, mImageView, mBitmapMask);
((Activity) mImageView.getContext()).runOnUiThread(images);
}
}
}
class DisplayImages implements Runnable {
Bitmap bitmap;
String urlString;
ImageView mImageView;
public DisplayImages(String urlString, ImageView mImageView, Bitmap bitmap) {
this.urlString = urlString;
this.mImageView = mImageView;
this.bitmap = bitmap;
}
public void run() {
if(!ImageViewReused(urlString, mImageView)){
if (bitmap != null)
mImageView.setImageBitmap(bitmap);
else
mImageView.setImageResource(default_icon);
}
}
}
private Bitmap DownloadFromUrl(String urlString) {
return decodeBitmapFromStream(urlString, getReqiredWidth(), getRequiredHeight());
}
private void addBitmapToMemoryCache(String key, Bitmap bitmap) {
synchronized (mMemoryCache) {
if (mMemoryCache.get(key) == null) {
mMemoryCache.put(key, bitmap);
}
}
}
private Bitmap getBitmapFromMemCache(String key) {
Bitmap bitmap = mMemoryCache.get(key);
if(bitmap == null){
bitmap = getBitmapFromDiskCache(key);
}
return bitmap;
}
private void addBitmapToDiskCache(String key, Bitmap bitmap) {
synchronized (mDiskLruImageCache) {
if (!mDiskLruImageCache.containsKey(String.valueOf(key.hashCode()))) {
mDiskLruImageCache.put(String.valueOf(key.hashCode()), bitmap);
addBitmapToMemoryCache(key, bitmap);
}
}
}
private Bitmap getBitmapFromDiskCache(String key) {
return mDiskLruImageCache.getBitmap(String.valueOf(key.hashCode()));
}
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
inSampleSize = Math.min(width/reqWidth, height/reqHeight);
return inSampleSize;
}
private static Bitmap decodeBitmapFromStream(String urlString, int reqWidth, int reqHeight) {
URL url = null;
InputStream is = null;
try {
url = new URL(urlString);
is = (InputStream) url.getContent();
} catch (Exception e) {
e.printStackTrace();
}
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// As InputStream can be used only once we have to regenerate it again.
try {
is = (InputStream) url.getContent();
} catch (IOException e) {
e.printStackTrace();
}
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(is, null, options);
}
public int getRequiredHeight() {
return requiredHeight;
}
public void setRequiredHeight(int longest, int requiredHeight) {
this.requiredHeight = requiredHeight > longest ? longest : requiredHeight;
}
public int getReqiredWidth() {
return requiredWidth;
}
public void setReqiredWidth(int longest, int requiredWidth) {
this.requiredWidth = requiredWidth > longest ? longest : requiredWidth;
}
public void clearCacheMemory() {
if(mMemoryCache.size() > 0){
mMemoryCache.evictAll();
}
}
public void clearDiskMemory() {
mDiskLruImageCache.clearCache();
}
}
希望你會得到一些想法,從上面的代碼提示..
不要這樣做。將ImageView保存在一個單獨的Hashtable中會導致內存泄漏並最終導致應用程序崩潰(通常是隱藏的「位圖超出VM預算」。)緩存文件中的位圖或字節,理想情況下使用WeakReferences,但永遠不會保存Drawables或Views(至少如果您的緩存持續存在於各個活動中),因爲它們保持對其包含的上下文的引用,這將保持原始包含的活動不被垃圾收集。看到這個Android開發人員的文章更多的:http://developer.android.com/resources/articles/avoiding-memory-leaks.html – 2010-11-26 17:13:00
是的,你是對的,我快速回答這個問題,沒有想到這種行爲,我總是使用自定義普通pojos做這個'緩存',但從來沒有使用ImageViews,所以我的appologies。 – Franco 2010-11-26 17:36:21