2013-02-08 22 views
1

我試圖實現一個圖像庫,它應該顯示〜5-15個較小的圖像和一個「當前選定」的較大圖像。內存泄漏圖像庫Android - 其他應用程序如何處理它?

它看起來像:http://www.mobisoftinfotech.com/blog/wp-content/uploads/2012/06/galleryDemo.png

我擡頭許多來源,現在決定使用位圖緩存(LRU高速緩存)(感謝這個論壇的人!)。

我不會在那一刻得到內存泄漏,但我不滿意這個解決方案,因爲每次我滾動,一些圖像從緩存中刪除,我已經重新加載他們......所以用戶一直等待重新加載圖像......這真是煩人等待0.5 - 1秒我每次滾動到另一側的時間...

public static WeakReference<Bitmap> getBitmap(String imageName, int width, 
     int height) { 
    if (!imageName.contains(".jpg")){ 
     imageName += ".jpg"; 
    } 
    String pathToImage = getPathToImage(imageName); 
    Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeFile(pathToImage, options); 

    /* 
    * Calculate inSampleSize 
    */ 
    options.inSampleSize = calculateInSampleSize(options, width, height); 

    /* 
    * Removes the alpha-channel from bitmap (not necessary) 
    */ 
    options.inPreferredConfig = Bitmap.Config.RGB_565; 

    /* 
    * Decode bitmap with inSampleSize set 
    */ 
    options.inJustDecodeBounds = false; 

    WeakReference<Bitmap> scaledBitmap = new WeakReference<Bitmap>(
      BitmapFactory.decodeFile(pathToImage, options)); 
    return scaledBitmap; 

難道我使獲得圖像的錯誤呢? 目前我將使用320x480分辨率的單選圖像和64x64的底部列表...

真的很奇怪的是,這並不重要,事實上,無論多大的決議圖像中,LRU緩存仍然會刪除一些圖像,即使我只選擇64×64的圖片... 我可能是做錯了事情與LRU緩存?

下面的代碼顯示了我實現:

/* 
    * Bitmaps which should be shown 
    */ 
    mMemoryCache = (BitmapCache) getLastNonConfigurationInstance(); 
    if (mMemoryCache == null) { 
     // Get max available VM memory, exceeding this amount will throw an 
     // OutOfMemory exception. Stored in kilobytes as LruCache takes an 
     // int in its constructor. 
     final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 

     // Use 1/4th of the available memory for this memory cache. 
     final int cacheSize = maxMemory/2; // TODO default 8 

     mMemoryCache = new BitmapCache(cacheSize); 
    } 

和類BitmapCache:

public BitmapCache(int maxSize, Resources resources) { 
    super(maxSize); 
    this.resources = resources; 
} 

@Override 
protected int sizeOf(String key, AsyncDrawable value) { 
    if (value.getBitmap() != null) { 
     /* 
     * The cache size will be measured in kilobytes rather than 
     * number of items. 
     */ 
     return value.getBitmap().getRowBytes() 
       * value.getBitmap().getHeight()/1024; 
    } 
    return super.sizeOf(key, value); 
} 

public void loadBitmap(Picture picture, ImageView mImageView, 
     ImageResolution resolution) { 
    if (cancelPotentialWork(picture.getFileName(), // + resolution.name() 
      mImageView)) { 
     final BitmapWorkerTask task = new BitmapWorkerTask(this, 
       mImageView, picture, resolution); 
     final AsyncDrawable asyncDrawable = new AsyncDrawable(resources, 
       null, task); 
     mImageView.setImageDrawable(asyncDrawable); 
     task.execute(); 
    } 
} 

非常感謝你:(

更多的代碼:BitmapWorkerTask:

@Override 
protected Bitmap doInBackground(Void... params) { 
    /* 
    * Decode image in background. 
    */ 
    final Bitmap bitmap = FileHandler.getBitmap(
      picture.getPictureId() + "", resolution).get(); 
    return bitmap; 
} 

@Override 
protected void onPostExecute(Bitmap bitmap) { 
    /* 
    * Once complete, see if ImageView is still around and set bitmap. 
    */ 
    if (isCancelled()) { 
     bitmap = null; 
    } 

    if (imageViewReference != null && bitmap != null) { 
     final ImageView imageView = imageViewReference.get(); 

     if (imageView != null) { 
      final Drawable drawable = imageView.getDrawable(); 
      if (drawable instanceof AsyncDrawable) { 
       final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; 
       final BitmapWorkerTask bitmapWorkerTask = asyncDrawable 
         .getBitmapWorkerTask(); 
       if (this == bitmapWorkerTask && imageView != null) { 
        imageView.setImageBitmap(bitmap); 
        bitmapCache.addBitmapToMemoryCache(
          picture.getFileName(), // + resolution.name() 
          asyncDrawable); 
       } 
      } 
     } 
    } 
} 
+1

是否有可能得到是當前立法院觀看圖像的最近鄰居並緩存..只是拋出一個想法在那裏 – smk 2013-02-08 15:40:43

+0

嘿,感謝您的想法!有可能找到最近的鄰居;)我認爲這可能是一個好主意來加載它們......但這並不能解決一些「快速」滾動操作,用戶只需從一側滑動到另一側。 ..我想其他的圖像顯示gallerys已經解決了這個問題...例如WhatsApp - 該組的媒體活動,我可以以最快的速度,我想滾動並沒有所需的拍攝圖像重新加載(或重新加載,不知何故好得多實施然後我的) – Frame91 2013-02-08 15:44:08

+1

它可能不是一個圖像加載的問題,但細胞回收? 我的意思是,當你快速滾動通過一個適配器,右側不使用電池會在左邊使用(這樣不會虛增一切)。 那麼,如果你快速滾動到左邊會發生什麼?它可能會連續啓動5個異步任務,但重複使用同一個單元2次。那麼當3個異步任務嘗試設置圖像時會發生什麼? – Redwarp 2013-02-09 16:45:34

回答

0

真棒!我發現它爲什麼不能工作的錯誤。錯誤在我的LruCache中,它存儲了AsyncDrawables,完全愚蠢。每當調用LruCache中的sizeOf時,asyncdrawable中的位圖都是null,所以他只返回了super.sizeOf(key,value)。

現在它就像一個魅力! :)

感謝您的幫助!