4

OOM の問題に関する何百もの記事を読みました。ほとんどは大きなビットマップに関するものです。256x256天気オーバーレイ タイルをダウンロードするマッピング アプリケーションを実行しています。ほとんどは完全に透明で、非常に小さいです。呼び出し中に 442 バイト長のビットマップ ストリームでクラッシュが発生しましたBitmapFactory.decodeByteArray(....).

例外は次のように述べています。

java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=9415KB, Allocated=5192KB, Bitmap Size=23671KB)

コードは次のとおりです。

protected Bitmap retrieveImageData() throws IOException {
    URL url = new URL(imageUrl);
    InputStream in = null;
    OutputStream out = null;
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();

    // determine the image size and allocate a buffer
    int fileSize = connection.getContentLength();
    if (fileSize < 0) {
        return null;
    }
    byte[] imageData = new byte[fileSize];

    // download the file
    //Log.d(LOG_TAG, "fetching image " + imageUrl + " (" + fileSize + ")");
    BufferedInputStream istream = new BufferedInputStream(connection.getInputStream());
    int bytesRead = 0;
    int offset = 0;
    while (bytesRead != -1 && offset < fileSize) {
        bytesRead = istream.read(imageData, offset, fileSize - offset);
        offset += bytesRead;
    }

    // clean up
    istream.close();
    connection.disconnect();
    Bitmap bitmap = null;
    try {
        bitmap = BitmapFactory.decodeByteArray(imageData, 0, bytesRead);
    } catch (OutOfMemoryError e) {
        Log.e("Map", "Tile Loader (241) Out Of Memory Error " + e.getLocalizedMessage());
        System.gc();
    }
    return bitmap;

}

デバッガーに表示される内容は次のとおりです。

bytesRead = 442

したがって、ビットマップ データは 442 バイトです。23671KB のビットマップを作成しようとしてメモリ不足になるのはなぜですか?

4

3 に答える 3

2

私は過去にこのような問題に遭遇しました。Android は Bitmap VM を使用し、非常に小さいです。ビットマップは必ず bmp.recycle で破棄してください。Android の新しいバージョンでは Bitmap VM が増えていますが、私が扱ってきたバージョンには 20MB の制限があります。

于 2011-09-03T04:06:41.693 に答える
0

このテーマについてはすでにいくつか読んでいるようですので、標準的な「ビットマップをデコードする方法は次のとおりです」というコメントは割愛します..

おそらく古いビットマップの参照を保持しているのではないかと思います (おそらくタイルは画面外に移動しましたが、配列のどこかにまだ参照があり、その結果、ガベージ コレクションされていませんか?) . これは過去に私をひどく悩ませました-メモリリークはデバッグが困難です。

私が同様の問題を抱えていたときに本当に助けになった素晴らしいGoogle I/O ビデオがここにあります。約 1 時間ですが、数日後に節約できることを願っています。次のような内容をカバーしています。

  1. ヒープ ダンプの作成
  2. DDMS でのヒープ使用量
  3. MAT を使用してヒープ ダンプを比較/分析する
于 2014-02-01T20:19:33.590 に答える
0

これはうまくいくかもしれません。ビットマップを低品質に縮小します。よくわかりませんが、これはメモリ内の画像を複製する可能性がありますが、簡単に試してみる価値があります。

            Bitmap image;
   image = BitmapFactory.decodeByteArray(data, 0, data.length);
   Bitmap mutableBitmap = image.copy(Bitmap.Config.ARGB_4444, true);
   Canvas canvas = new Canvas(mutableBitmap); 

以下の私の古い答えは、ストリーミングで機能するとは思いません。

                Options options = new BitmapFactory.Options();
        Options options2 = new BitmapFactory.Options();
        Options options3 = new BitmapFactory.Options();

        options.inPreferredConfig = Bitmap.Config.ARGB_8888;///////includes alpha
        options2.inPreferredConfig = Bitmap.Config.RGB_565 ;///////no alpha
        options3.inPreferredConfig = Bitmap.Config.ARGB_4444 ;/////alpha lesser quality

        image=BitmapFactory.decodeResource(getResources(),R.drawable.imagename,options); 
        image=Bitmap.createScaledBitmap(image, widthx,height, true);  
于 2012-09-13T01:51:50.593 に答える