2013-08-23 26 views
7

私はandroid:backgroundを使用して、アンドロイドのレイアウトに背景画像を与えます。
いくつかの画像を入れた後、私はこの例外を取得:
OutOfMemory大きな背景画像を読み込むとき

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


は、どのように私は、Android上の背景として拡大イメージを使用することができますか?
アプリケーションのヒープメモリを拡張できますか?それとも良いことではないのですか?

+3

これらの質問の多くで言及したように、巨大な(あなたのケースでは> 30MB)背景画像を使用しないでください。 – kabuko

+2

このようなStackOverFlowには、多くの類似の質問があります。私はこれを解決するための多くの選択肢の要約をしようとしました:http://stackoverflow.com/questions/11820266/android-bitmapfactory-decodestream-out-of-memory-with-a-400kb-file-with-2mb- f/16528487#16528487 –

+0

非常に大きな画像を使用しないことから離れて、機器の容量を考慮する必要があります、実際の問題は、デバイスがその巨大な画像の背景のように充電する容量を持っていないということです。 –

答えて

7

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

High resolution Image - OutOfMemoryError

は可能な限り小さく背景画像を維持することで、アプリケーションのメモリ使用量を最小限に抑えるようにしてください。

これを介して行うことができる:それもアプリ

  • でそれを使用して以下を使用する前に、画面
  • (例えばフォトショップを使用して)、さらに画像を圧縮収まるように画像をトリミング

    • あなたはメモリ
    • での複数のインスタンスを保持していないことを確認するとすぐ無logerが
    • それを必要として、ビットマップを再利用し、あなたのビットマップをロードする方法10
    • はビットマップ

    あなたが背景として設定した画像が正しくロードされていることを確認してくださいを使用した後はnullへの参照を設定する(例えば、例えば画面サイズに合うようにサイズが切り取られる)、もはやそれらがもはや必要でなくなるとすぐにメモリから解放される。

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

    これは、あなたの画像を読み込むことができるかです:コードのこの美しい作品のためAdam Stelmaszczyk

    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; 
    } 
    

    感謝。

  • +0

    ちょっと、ビットマップを使用した後、nullへの参照を設定するとどういう意味ですか? –

    5

    レイアウトの背景イメージのため、同様の問題が発生しました。イメージのメモリ割り当ての通常のサイズは、height * width * 4バイト(デフォルトモードのARGB_8888モード)でなければなりません。

    アクティビティを表示しているときに30MBが表示されている場合は、何らかの問題がある必要があります。ドローイング可能なフォルダに背景画像を置いているかどうか確認してください。その場合、システムはその画像を画面の特定の濃度に拡大しなければならず、大きなメモリオーバヘッドが発生します。

    ソリューション:

    1. プレイス各描画可能なフォルダ内の背景画像の特定のバージョン(MDPI、hdpi、xhdpi ...)。
    2. "drawable-nodpi"という特別なリソースフォルダに背景イメージを配置します。システムは、このディレクトリに置かれた画像を拡大縮小しようとはしません。そのため、ストレッチ処理が実行され、割り当てられたメモリが予想されます。

    このanswer

    での詳しい情報は、この情報がお役に立てば幸いです。

    +0

    これはグラフィックスのメモリ割り当てを半分に削減しました!ありがとうございました! – Magritte

    1

    can I expand the application heap memory?

    はい、可能です。 Manifest.xmlにandroid:largeHeap:="true"と設定してください。

    <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"> 
    
    +0

    これは動作しません、アプリはまだメモリが不足していると、また、あなたのアプリを遅くすることができます、largeHeap on。 https://developer.android.com/training/articles/memory.html さらに、大きなヒープサイズはすべてのデバイスで同じではなく、RAMが限られているデバイスで実行している場合、大きなヒープサイズは通常のヒープサイズと同じです。したがって、大きなヒープサイズを要求したとしても、getMemoryClass()を呼び出して通常のヒープサイズをチェックし、常にその上限を下回るようにしてください。 – Nickmccomb

    +0

    この機能を設定すると、マップフラグメント(最大30kの地理マーカーを表示)の問題を解決しました...そして確かに、すべてのデバイスのRAMが限られているため、可能な限り低いリソースを消費するコードを生成する必要がありますデータをキャッシュする方が良いこともありますが、CPUを使用することをお勧めします)。この時点で誰も短い答えを出すことはできません。しかし、私が言ったように、上のこのスニペットは、状況によっては私のためのトリックを行った。だから、 "これは動作しません"と言って間違っている。 –

    +0

    私は同意しません。私は解決策があなたのアプリを遅らせるべきではないと思って、道に沿ってもっと多くの問題を導入してください。ビットマップを悪用してメモリ不足エラーが発生するため、アプリケーションが動作していません。あなたの "解決策"はこれを修正しません。なぜなら、ビットマップが使用可能なメモリのサイズ(修正されていないかもしれません)であっても、もう一度ビットマップが導入されると間違いなくOOMエラーが発生するからです。それは解決策ではありません。 – Nickmccomb

    3

    私は同じ問題を抱えていたし、次でそれを修正:

    1. は描画可能nodpiフォルダを作成し、そこにあなたの背景画像を置きます。それはあなたが行う場合は

      ImageView ivLogo = (ImageView) findViewById(R.id.ivLogo); 
      Picasso.with(getApplicationContext()) 
          .load(R.drawable.logo) 
          .fit() 
          .centerCrop() 
          .into(ivLogo); 
      

      に必要がある場合http://square.github.io/picasso/

    は.fit()と.centerCrop()とピカソとそれらを表示する画像を表示する

  • 使用ピカソは、画像を拡大縮小します何とかメモリが使い果たされると、ピカソはOOMエラーを表示するのではなく、画像を表示しません。私はこれが助けて欲しい!

  • 関連する問題