2016-05-30 191 views
1

我正在構建一個帶有圖像的音樂應用程序,我正在使用Picasso加載圖像。我在畢加索使用的目標如下:Android:內存不足

Target target = new Target() { 

    @Override 
    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { 
     try { 

      if (artNormal != null) { 
       artNormal.recycle(); 
       artNormal = null; 
      } 

      artNormal = Bitmap.createBitmap(bitmap); 
      TransitionDrawable td = null; 


      if (upNextShowing) { 

       Bitmap scaled = Bitmap.createScaledBitmap(artNormal, 10, 10, true); 
       td = new TransitionDrawable(new Drawable[]{ 
         playerArt.getDrawable(), 
         new BitmapDrawable(context.getResources(), scaled) 
       }); 

       // Updated Part -- Updated Part 
       if(scaled!=null){ 
       scaled.recycle(); 
       scaled = null; 
      } 

      } else { 

       td = new TransitionDrawable(new Drawable[]{ 
         playerArt.getDrawable(), 
         new BitmapDrawable(context.getResources(), bitmap) 
       }); 

      } 
      td.setCrossFadeEnabled(true); 
      playerArt.setImageDrawable(td); 
      td.startTransition(1000); 

      new GetBlurredAlbumArt(artNormal).execute(); 

     } catch (Exception e) { 

      e.printStackTrace(); 
      Log.e("LargePlayer", "Error :" + e.getLocalizedMessage()); 
      Log.e("LargePlayer", "Error :" + e.getCause()); 
     } 

    } 

    @Override 
    public void onBitmapFailed(Drawable errorDrawable) { 
     Log.e("LargePlayer", "Picasso Load Failed"); 
     TransitionDrawable td = null; 
     if (artNormal != null) { 
      artNormal.recycle(); 
      artNormal = null; 
     } 
     artNormal = BitmapFactory.decodeResource(context.getResources(), 
       R.drawable.album_art_large); 
     artNormal = Bitmap.createScaledBitmap(artNormal, 800, 800, true); 

     if (upNextShowing) { 

      Bitmap scaled = Bitmap.createScaledBitmap(artNormal, 10, 10, true); 
      td = new TransitionDrawable(new Drawable[]{ 
        playerArt.getDrawable(), 
        new BitmapDrawable(context.getResources(), scaled) 
      }); 

       // Updated Part -- Updated Part 
       if(scaled!=null){ 
       scaled.recycle(); 
       scaled = null; 
      } 

     } else { 

      td = new TransitionDrawable(new Drawable[]{ 
        playerArt.getDrawable(), 
        new BitmapDrawable(context.getResources(), BitmapFactory.decodeResource(context.getResources(), 
          R.drawable.album_art_large)) 
      }); 

     } 
     td.setCrossFadeEnabled(true); 
     playerArt.setImageDrawable(td); 
     td.startTransition(1000); 
     new GetBlurredAlbumArt(artNormal).execute(); 

    } 

    @Override 
    public void onPrepareLoad(Drawable placeHolderDrawable) { 

    } 

}; 
class GetBlurredAlbumArt extends AsyncTask<Void, Void, Bitmap> { 

    Bitmap bitmap; 

    public GetBlurredAlbumArt(Bitmap bitmap) { 
     this.bitmap = bitmap; 

    } 

    @Override 
    protected Bitmap doInBackground(Void... params) { 

     bitmap = Bitmap.createScaledBitmap(bitmap, 300, 300, true); 

     bitmap = ImageUtilties.fastblur(bitmap, 100); 

     try { 
      return bitmap; 
     } catch (Exception e) { 
      Log.e("LargePlayer", "Error :" + e.getLocalizedMessage()); 
      Log.e("LargePlayer", "Error :" + e.getCause()); 
     } 
     return bitmap; 
    } 

    @Override 
    protected void onPostExecute(Bitmap bitmap) { 
     super.onPostExecute(bitmap); 

     TransitionDrawable td = new TransitionDrawable(new Drawable[]{ 
       blurredColors.getDrawable() != null ? blurredColors.getDrawable() : new ColorDrawable(Color.WHITE), 
       new BitmapDrawable(context.getResources(), bitmap) 
     }); 

     td.setCrossFadeEnabled(true); 
     blurredColors.setImageDrawable(td); 

     td.startTransition(1000); 


    } 
} 

每次圖像更改時,內存消耗增加2-3 MB。內存使用量可能增加到200 MB(這肯定是不可接受的)。活動中只有2個圖像視圖發生變化。圖像尺寸接近1200x1200。我知道它們非常大,但是我在每次設置之前都會循環使用位圖,但內存使用情況仍然會像任何情況一樣增加。該應用程序崩潰後。它也有時會給出錯誤嘗試使用回收的位圖。也試過

android:largeHeap="true" 

但我需要減少內存使用量。請幫忙!

+1

採取這裏看看[鏈接](http://stackoverflow.com/questions/477572/strange-out-of-memory-issue-while-loading-an-image-to-a-位圖對象) –

+0

我想這個鏈接是關於加載時縮放位圖的。但畢加索使用resize()調整圖像本身。你是說畢加索在加載到內存後調整圖像大小? –

回答

2

一個解決方案是嘗試根據屏幕的分辨率顯示圖像。爲此,只要應用程序啓動,將寬度和高度像素存儲在您的SharedPreferences中,然後使用它來加載縮小版本的圖像。我建議的另一種解決方案是,如果可能的話,嘗試使用Fresco。它使用可以存儲大量數據的ashmem cache。我個人面臨Picasso這個問題,並找不到一個優雅的解決方案,但切換到Fresco後,所有這些OOM錯誤都消失了。

+0

是免費的用於商業用途的壁畫? –

+0

我想是的。它絕對是開源的。但是,如果你有任何疑慮,不妨問問他們。 –

+0

我會嘗試一下,但我的主要目標不是增加緩存大小,而是減少整體內存使用量。 –

1

當你解碼第二個位圖時,第一個位圖沒有被GC'ed,因爲你創建了許多位圖副本,因此你需要位圖ASAP使用的可用內存和回收。

https://developer.android.com/training/displaying-bitmaps/manage-memory.html

+0

我沒有得到你。每當picasso成功放置一個圖像時,它會轉到onBitmapLoaded()函數,如果該位置不爲null,那麼我將回收位圖。 –

+0

我檢查你是否複製或解碼文件或縮放以製作新的位圖,而不是在完成時回收它們。 – phongvan

+0

即使範圍被清空,位圖是否仍保留在內存中? –