0

私はAndroidの初心者です!巨大なビットマップ (> 1200 * 1000) を使用するアプリを開発しているため、Android の SDK にいくつかの大きな問題があります。アプリの実行中に同じサイズの複数のレイヤー/ビットマップ (3-5 個) が必要です。 . 問題は、メモリ ヒープがこれらの割り当ての 1 つで非常に急速に消費され、OutOfMemory 例外がトリガーされることです。

良い点は、すべてのビットマップを同時に必要としないことです。

recycle() メソッドの呼び出しを試みましたが、ビットマップのメモリがネイティブ メモリではなくヒープに存在するため、廃止されていることは理解していました。また、特定のビットマップからすべての参照を削除しようとしましたが、 System.gc() を手動で呼び出しても使用できませんでした。ビットマップを削除できませんでした。わかりました、私が知らないメモリリークがあるかもしれませんが、私はそれを疑っています.

私はあらゆる種類の解決策を試しましたが、どれもうまくいきません。

私にとって最良の選択はビットマップを再利用することでしたが、BitmapFactory のデコード メソッドは、メモリを消費する新しいビットマップを割り当てることしか知りません。

私の質問は、Android で動作するビットマップ ピクセルを再利用する (別のビットマップ/ピクセル配列を割り当てずにビットマップのピクセルを上書きする) 方法を知っていますか ??? 問題は、GarbageCollector ソリューションに常駐できないことです。これらのビットマップがメモリから削除されているか、他のビットマップが割り当てられていないことを確認する必要がある特定の瞬間がアプリにあるためです。

別の解決策は次のとおりです。ヒープメモリを通過せずに、ビットマップをSDカードに直接描画する方法を知っていますか? 大きなビットマップ (元のサイズの 2 倍) を割り当てて、他の 2 つの処理済みビットマップを連結しようとすると、クラッシュする瞬間があります) ... それが私が尋ねている理由です。Canvas や他の描画オブジェクトをデータ ストリームから直接インスタンス化する可能性はありますか?

他の解決策は、ヒープメモリをシミュレートする仮想スワップメモリ​​のようなものを利用することですが、SDCARDまたは何かにキャッシュします。しかし、これを行う方法も見つかりません。

4

3 に答える 3

2

カスタムビットマップ操作を実行するための別のクラスを作成します。

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;


class BitmapLoader
{
public static int getScale(int originalWidth,int originalHeight,
   final int requiredWidth,final int requiredHeight)
{
    //a scale of 1 means the original dimensions 
    //of the image are maintained
    int scale=1;

    //calculate scale only if the height or width of 
    //the image exceeds the required value. 
    if((originalWidth>requiredWidth) || (originalHeight>requiredHeight)) 
    {
        //calculate scale with respect to
        //the smaller dimension
        if(originalWidth<originalHeight)
            scale=Math.round((float)originalWidth/requiredWidth);
        else
          scale=Math.round((float)originalHeight/requiredHeight);

    }

    return scale;
}

public static BitmapFactory.Options getOptions(String filePath,
        int requiredWidth,int requiredHeight)
{

    BitmapFactory.Options options=new BitmapFactory.Options();
    //setting inJustDecodeBounds to true
    //ensures that we are able to measure
    //the dimensions of the image,without
    //actually allocating it memory
    options.inJustDecodeBounds=true;

    //decode the file for measurement
    BitmapFactory.decodeFile(filePath,options);

    //obtain the inSampleSize for loading a 
    //scaled down version of the image.
    //options.outWidth and options.outHeight 
    //are the measured dimensions of the 
    //original image
    options.inSampleSize=getScale(options.outWidth,
            options.outHeight, requiredWidth, requiredHeight);

    //set inJustDecodeBounds to false again
    //so that we can now actually allocate the
    //bitmap some memory
    options.inJustDecodeBounds=false;

    return options;

}



public static Bitmap loadBitmap(String filePath,
        int requiredWidth,int requiredHeight){


    BitmapFactory.Options options= getOptions(filePath,
            requiredWidth, requiredHeight);

    return BitmapFactory.decodeFile(filePath,options);
}
}

次に、アクティビティから、Bitmap reqBitmap = loadBitmap(String filePath,int requiredWidth,int requiredHeight)このクラスのメソッドを呼び出しfilepathて、SDカードから取得したビットマップのを提供し、requiredWidthとrequiredHeightをビットマップを拡大縮小するサイズに設定します。次に、を使用しreqBitmapます。

このようにして、大きなビットマップはヒープメモリにロードされる前に縮小されます。私は同じ問題を抱えていました、そしてこれは私のためにそれを解決しました。:)

于 2012-10-22T12:37:23.127 に答える
1

私はうまくいかなかったのと同じような問題を抱えていrecycle()ました。だから私は set と同じくらい些細なことをしましたmyBitmap = null。これは、myBitmap が逆参照され、不要になったことをガベージ コレクターに示します。したがって、ヒープを解放する仕事をします。次に、 myBitmap を使用して、メモリ例外なしで新しいビットマップをロードできます。

于 2012-10-22T13:52:06.177 に答える
0

手遅れかもしれませんが、「BitmapFactory.Options.inBitmap」を使用することをお勧めします。設定されている場合、skia はこのビットマップを再利用して画像をデコードしようとします。 http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inBitmap

于 2013-02-27T22:38:40.790 に答える