2016-10-22 3 views
0

私はアンドロイドアプリを開発しています。私はそこにたくさんのビットマップを扱わなければなりません。場合によっては、メモリ不足のためにアプリがクラッシュすることがあります。ビットマップのリストを効率的に処理し、メモリ不足のエラーを回避する方法

私はカスタムオブジェクト(ソングクラス)を持っています。タイトル、アーティスト、リンク、ビットマップなどのフィールドがあります。オーディオストリームからアルバムのカバーを取得し、そのビットマップを関連するオブジェクトのフィールドに割り当てます。ここで

は、アルバムカバーのビットマップを取得するためのコード、

public static CustomBitmap downloadAudioCover(Context context, final String url) { 
    final MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever(); 
    try { 
     metaRetriever.setDataSource(url, new HashMap<String, String>()); 
     final byte[] art = metaRetriever.getEmbeddedPicture(); 
     int width = context.getResources().getDimensionPixelSize(R.dimen.image_audio_cover_width); 
     int height = context.getResources().getDimensionPixelSize(R.dimen.image_audio_cover_height); 
     CustomBitmap customBitmap = new CustomBitmap(); 
     customBitmap.setBitmap(decodeSampledBitmapFromResource(art, width, height)); 
     return customBitmap; 
    } catch (Exception e) { 
     return null; 
    } 
} 

ここで私は、私は再び上記のプロセスを避けることができるように、オブジェクトをシリアル化してファイルに保存することCustomBitmapクラスを使用し、次回きていますユーザーは、アプリケーションのユーザーに来ると、遅滞なく、アルバムの表紙を見ることができます。

問題は約50曲あります。これは、50個のオブジェクトを50ビットマップで保持する必要があることを意味します。

このデータを表示するには、RecyclerViewを使用しています。

私は最初にビットマップを持っていないので、私はすべての単一の曲のために上記の方法を呼び出す必要があります。だから私は最初に(ビットマップなしで)曲を取得し、すべての曲をフェッチした後、私はビットマップを取得するために配列リストをループします。すべてのビットマップを取得したら、アダプタでnotifyDataSetChangedメソッドを呼び出します。

このプロセスでは、メモリがより多く消費されます。私は私のアプリでビットマップのこのリストを処理するためのより効率的な方法が必要です。任意の提案をいただければ幸いです。

*ビットマップをonBindViewHolderの中に入れて、これにオブジェクトを割り当てないでイメージビューに設定していますか?

ありがとうございました。

注:これはあなたがイメージをロードするためのライブラリを使用する必要があるビットマップ

private static Bitmap decodeSampledBitmapFromResource(byte[] arr, int reqWidth, int reqHeight) { 
    // First decode with inJustDecodeBounds=true to check dimensions 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeByteArray(arr, 0, arr.length, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeByteArray(arr, 0, arr.length, options); 
} 


    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; 

    if (height > reqHeight || width > reqWidth) { 
     final int halfHeight = height/2; 
     final int halfWidth = width/2; 

     // Calculate the largest inSampleSize value that is a power of 2 and keeps both 
     // height and width larger than the requested height and width. 
     while ((halfHeight/inSampleSize) >= reqHeight && (halfWidth/inSampleSize) >= reqWidth) { 
      inSampleSize *= 2; 
     } 
    } 

    return inSampleSize; 
} 
+0

[Glide](https://github.com/bumptech/glide)を試してみましたか? – Max

+0

私はしていません。私は他の画像を読み込むためにこのアプリでユニバーサル画像ローダーを使用しています。しかし、あなたは、オーディオストリームからビットマップを取得し、setImageBitmapメソッドのみを使用してイメージビューに設定することがわかります。 – chathura

+0

Facebookで[Fresco](https://github.com/facebook/fresco)画像読み込みライブラリを使用してください。すべてのイメージをリサイクルし、メモリをクリアすることで、すべてのOOMの問題を自動的に軽減します。私自身の経験では、UILは多くのOOMの問題を引き起こします。フレスコ画を使用すると、あなたは満足します:P –

答えて

1

をサンプリングするためのコードです。

Glideは、画像を読み込むための素晴らしいライブラリです。

すべての依存関係の最初に

あなたのbuild.gradleに

compile 'com.github.bumptech.glide:glide:3.7.0' 

をこれら二つを入れて、その後、あなたがイメージをロードするアダプタであなたがするneeedすべては次のとおりです。

Glide 
    .with(context) 
    .load(AudioArt) 
    .into(yourImageView); 

お客様のニーズに合わせてカスタマイズすることもできます。Github Pageにアクセスしてください。

Future Studioにもカスタマイズに関する素晴らしいチュートリアルがあります。

+0

それはオーディオストリームでビットマップを取得していますか?私は思う? – chathura

+0

です。 Variable AudioArtは '' byte [] ''です。がんばろう!) –

関連する問題