-8

重複の可能性:
java.lang.OutOfMemoryError: ビットマップ サイズが VM の予算を超えています - Android

現在、URL からダウンロードした画像を表示して ListView に配置する Android アプリを開発しています。そしてクリックされると、クリックされた画像の新しい ImageView を作成します。小さい画像 (7kb) をクリックすると、正常に動作します。200kb までは正常に動作します。しかし、それよりも大きいと、「アプリケーションが予期せず停止しました。もう一度やり直してください。」というエラーが表示されます。LogCat を見ると、問題は Android のメモリ不足に関係しているようです。これに対する解決策はありますか?それとも、画像の解像度を 200kb の範囲まで下げる必要があるだけですか? 確かに、画像サイズは 1 メガバイトまたは 2 メガバイトまではあまり問題にならないはずですか? 読み込みに少し時間がかかる場合がありますが、エラーがスローされる理由はわかりません。

どんな助けでも大歓迎です!

Zoom.java

public class Zoom extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.gallery_zoom);

        String selection = getIntent().getExtras().getString("image");
        Toast.makeText(this, selection, Toast.LENGTH_LONG).show();

        new backgroundLoader().execute();
    }


    public class backgroundLoader extends AsyncTask<Void, Void, Void> {
        Bitmap bmp;

        @Override
        protected Void doInBackground(Void... params) {
            BitmapFactory.Options bmpOptions;
            bmpOptions = new BitmapFactory.Options();
            bmpOptions.inSampleSize = 1;
            bmp = LoadImage(getIntent().getExtras().getString("image"), bmpOptions);
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            ImageView image = (ImageView) findViewById(R.id.imageZoom);
            image.setImageBitmap(bmp);
            super.onPostExecute(result);
        }

    }

    private Bitmap LoadImage(String URL, BitmapFactory.Options options) {
        Bitmap bitmap = null;
        InputStream in = null;
        try {
            in = OpenHttpConnection(URL);
            bitmap = BitmapFactory.decodeStream(in, null, options);
            in.close();
        } catch (IOException e1) {
        }
        return bitmap;

    }

    private InputStream OpenHttpConnection(String strURL) throws IOException {
        InputStream inputStream = null;
        URL url = new URL(strURL);

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        try {
            InputStream in = new BufferedInputStream(connection.getInputStream());
            return in;
        } catch (Exception exception) {
            exception.printStackTrace();
            return null;
        }
    }

}

LogCat ログ

08-13 07:35:01.798: E/dalvikvm-heap(1132): 48064000-byte external allocation too large for this process.
08-13 07:35:01.888: E/GraphicsJNI(1132): VM won't let us allocate 48064000 bytes
08-13 07:35:01.888: D/dalvikvm(1132): GC_FOR_MALLOC freed 1K, 54% free 2694K/5831K, external 2229K/3423K, paused 19ms
08-13 07:35:01.888: D/skia(1132): --- decoder->decode returned false
08-13 07:35:01.888: W/dalvikvm(1132): threadid=14: thread exiting with uncaught exception (group=0x40015560)
08-13 07:35:01.898: E/AndroidRuntime(1132): FATAL EXCEPTION: AsyncTask #1
08-13 07:35:01.898: E/AndroidRuntime(1132): java.lang.RuntimeException: An error occured while executing doInBackground()
08-13 07:35:01.898: E/AndroidRuntime(1132):     at android.os.AsyncTask$3.done(AsyncTask.java:200)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at java.util.concurrent.FutureTask.run(FutureTask.java:138)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at java.lang.Thread.run(Thread.java:1019)
08-13 07:35:01.898: E/AndroidRuntime(1132): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
08-13 07:35:01.898: E/AndroidRuntime(1132):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at com.example.example.mobile.application.gallery.Zoom.LoadImage(Zoom.java:72)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at com.example.example.mobile.application.gallery.Zoom.access$0(Zoom.java:67)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at com.example.example.mobile.application.gallery.Zoom$backgroundLoader.doInBackground(Zoom.java:54)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at com.example.example.mobile.application.gallery.Zoom$backgroundLoader.doInBackground(Zoom.java:1)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
08-13 07:35:01.898: E/AndroidRuntime(1132):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
08-13 07:35:01.898: E/AndroidRuntime(1132):     ... 4 more
08-13 07:35:01.908: W/ActivityManager(61):   Force finishing activity com.example.example.mobile.application/.gallery.Zoom
4

3 に答える 3

1

まず、200Kb が圧縮された jpg 形式であることを知っておく必要があります。Android は、画像をビットマップ非圧縮形式で保存します。写真のサイズによっては、写真あたり最大数メガバイトになる場合があります。

問題を最小限に抑えるには、BitmapFacotry insamplesize メソッドを参照してください。

http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize

画像を開くことができますが、解像度は低くなります (2 のべき乗)。

また、積極的に呼び出すようにしてください:

mybitmap = null;
System.gc;
System.runFinalization;
System.gc;

できるたびに。

于 2012-08-16T10:53:22.210 に答える
1

いくつかの考え

  1. ビットマップへの参照を AsyncTask 内に保持しないでください。Bitmap を Void ではなく param として定義して適切に使用してください。ここで勉強してください。

  2. ビットマップをリサイクルする必要がある場合があります。ビットマップの処理方法については、こちらのAndroid デベロッパー トレーニングを参照してください。

  3. 学習メモリ分析ツール (MAT)はこちら.

于 2012-08-16T11:03:16.583 に答える
1

VM のメモリ制限に到達しないように、より複雑なキャッシュ方法を検討することをお勧めします。リソースの優れた場所は、Android 独自の事前レッスン サイトです。チュートリアルの最も重要な部分は、VM のメモリ制限のパーセンテージに制限された LRUCache を作成することです。

http://developer.android.com/training/displaying-bitmaps/index.html

于 2012-08-16T10:49:50.950 に答える