2016-05-30 111 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

即使范围被清空,位图是否仍保留在内存中? –