2016-05-30 13 views
1

私は画像が入った音楽アプリを作成しています。画像を読み込むためにPicasaを使用しています。ピカソで使用しているターゲットは、次のとおりです。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〜3MB増加します。メモリ使用量は最大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

リンクは、ロード時にビットマップのスケーリングに関するものだと思います。しかし、Picassoはresize()を使ってイメージ自体のサイズを変更します。メモリにロードされた後、ピカソがイメージのサイズを変更すると言っていますか? –

答えて

2

解決策の1つは、画面の解像度に従って画像を表示しようとすることです。そのために、アプリケーションが起動するとすぐに、あなたのSharedPreferencesに幅と高さのピクセルを格納し、それを使ってイメージの縮小版を読み込みます。可能であれば、私が助言する他の解決策は、Frescoを試してみることです。大量のデータを格納できるashmem cacheを使用します。私は個人的にPicassoでこの問題に直面しており、優雅な解決策を見つけることができませんでしたが、Frescoに切り替えた後、それらのOOMエラーはすべて消えました。

+0

は商業利用のために無料で利用できますか? –

+0

そうですね。それは間違いなくオープンソースです。しかし、あなたが心配しているなら、それらに尋ねてください。 –

+0

私はそれを試しますが、私の主な目的は、キャッシュサイズを増やすことではなく、全体のメモリ使用量を減らすことです。 –

1

ビットマップの多くのコピーを作成するため、リサイクルを使用してビットマップASAPで空きメモリを使用する必要があるため、2番目のビットマップをデコードすると、最初のビットマップはGCされません。

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

+0

私はあなたを得ませんでした。ピカソが画像を正常にlaodするたびに、関数はonBitmapLoaded()に行きます。ここでは、nullでない場合はビットマップをリサイクルしています。 –

+0

ファイルやスケールをコピーまたはデコードして新しいビットマップを作成し、完了したらリサイクルしないことを確認します。 – phongvan

+0

ビットマップはスコープが埋め込まれていてもメモリに残りますか? –