8

android:backgroundAndroidレイアウトに背景画像を与えるために使用しています。
いくつかの画像を配置した後、次の例外が発生します。

08-24 00:40:19.237: E/dalvikvm-heap(8533): Out of memory on a 36000016-byte allocation.


Androidで大きな画像を背景として使用するにはどうすればよいですか?
アプリケーション ヒープ メモリを拡張できますか? それとも良くないことですか?

4

6 に答える 6

8

私の関連する質問を見てください:

高解像度画像 - OutOfMemoryError

背景画像をできるだけ小さくして、アプリケーションのメモリ使用量を最小限に抑えるようにしてください。

これは次の方法で実行できます。

  • 画面に収まるように画像をトリミングする
  • アプリで使用する前に、画像をさらに圧縮します(Photoshopなどを使用)
  • 以下の方法を使用してビットマップをロードします
  • 必要がなくなったらすぐにビットマップをリサイクルします
  • 複数のインスタンスをメモリに保持しないようにしてください
  • ビットマップを使用した後、参照を null に設定します

背景として設定した画像が適切に読み込まれ (たとえば、画面サイズに合わせてサイズがトリミングされている)、不要になったらすぐにメモリから解放されていることを確認してください。

メモリ内にビットマップのインスタンスが 1 つだけあることを確認してください。表示したら、呼び出しrecycle()て参照を null に設定します。

画像をロードする方法は次のとおりです。

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
        int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

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

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

public 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) {

        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    return inSampleSize;
}

この美しいコードを提供してくれたAdam Stelmaszczykに感謝します。

于 2013-08-23T22:11:04.067 に答える
6

レイアウトの背景画像が原因で、同様の問題が発生しました。画像のメモリ割り当ての通常のサイズは、高さ * 幅 * 4 バイトです (モード ARGB_8888、デフォルト モード)。

アクティビティを表示するときに 30MB の割り当てが表示される場合は、何らかの問題があるはずです。背景画像を drawable フォルダーに配置しているかどうかを確認します。その場合、システムはその画像を画面の特定の密度に合わせてスケーリングする必要があり、メモリのオーバーヘッドが大きくなります。

ソリューション:

  1. 各ドローアブル フォルダー (mdpi、hdpi、xhdpi...) に特定のバージョンの背景画像を配置します。
  2. 背景画像を「drawable-nodpi」という特別なリソース フォルダーに配置します。システムはこのディレクトリに配置された画像をスケーリングしようとしないため、ストレッチ プロセスのみが実行され、割り当てられたメモリは期待どおりになります。

この回答の詳細

お役に立てれば。

于 2014-01-17T10:38:34.627 に答える
1

アプリケーション ヒープ メモリを拡張できますか?

はい、できます。android:largeHeap:="true"Manifest.xml に設定するだけです。

   <application
        android:name="com.pepperonas.libredrive.App"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:largeHeap="true"
        android:label="@string/app_name"
        android:launchMode="standard">
于 2015-12-14T16:46:50.553 に答える
0

画像をキャッシュしてメモリからロードするのに役立つGlideを使用してください

Glide  
    .with(/*context*/)
    .load(/*urlToImage*/)
    .thumbnail(0.5f/*scale*/)  //you can even downscale the image
    .into(imageView);

次に、Glide を使用すると、OnScrollChangedListener

if(scrollState == SCROLL_STATE_IDLE){
    Glide.with(this /*context*/).resumeRequests();
} else if(scrollState == SCROLL_STATE_TOUCH_SCROLL ||
          scrollState == SCROLL_STATE_FLING){
 Glide.with(this).pauseRequests();
}
于 2018-09-17T23:35:45.437 に答える