0

を呼び出すビューアアプリケーションを作成していますBitmapRegionDecoder.decodeRegion(Rect, BitmapFactory.Options)decodeRegion各呼び出しの前に以前に取得したビットマップを破棄しています。

//this is a function I wrote that gets the rectangle I need
//from the zoom/pan state of a lower-resolution ImageView (page).
//it is bragable.
Rect areaRect = page.getBitmapRegionDecoderRect(areaBitmapRect);
BitmapFactory.Options options = new BitmapFactory.Options();

//area is the ImageView which will get the hi-res bitmap in it.
if(area.getHeight()!=0)
{
//I used Math.round because we are so desperate to save memory!
//The consequent blurring is actually not too bad.
    options.inSampleSize = Math.round( ((float) areaRect.height()) / ((float) area.getHeight()) );
}
else
{
    options.inSampleSize = Math.round( ((float) areaRect.height()) / ((float) page.getHeight()) );
}
if(options.inSampleSize==0) options.inSampleSize=1;
if(options.inSampleSize>16) options.inSampleSize=16;
options.inPreferredConfig = Bitmap.Config.RGB_565;
if(areaRect.left<0) areaRect.left = 0;
if(areaRect.right>areaBitmapRect.right) areaRect.right = areaBitmapRect.right;
if(areaRect.top<0) areaRect.top = 0;
if(areaRect.bottom>areaBitmapRect.bottom) areaRect.bottom = areaBitmapRect.bottom;
if(areaBitmap!=null)
{
//recycling our garbage ... or are we?
    areaBitmap.recycle();
    areaBitmap = null;
    try
    {
//dirty hack
        wait(200);
    }
    catch(Exception x)
    {
//something happened.
    }
}
//the all-important call
areaBitmap = areaDecoder.decodeRegion(areaRect, options);
area.setImageBitmap(areaBitmap);

非常に高速な連続UIイベントで、メモリが不足しているという事実に問題がありました。ご覧のとおり、私はこれをダーティハックで「解決」しました(スレッドは200ミリ秒待機し、Androidに追いつくのに少し時間がかかります)。

明らかな理由で、私はこれにあまり満足していません。まず、私の診断(新しいメモリを割り当てる前にガベージコレクションが終了していない)は正しいですか?第二に、私は入れてみました

while(!areaBitmap.isRecycled())

呼び出し後のカウンタの増分の前後で、recycle()カウンタはゼロのままでした。私はこれを行うことに意味がありますが、代わりにメソッドisRecycled()のようなものが必要です。isCompletelyRecycled()Androidにはこのようなものがありますか?第三に、これでどこにも行けない場合、私の呼び出しが私たちを押しのけるかどうかを判断するために使用できる「使用可能なメモリ」メソッドはありますか?見つかりません。Androidが「より多くのコアを利用可能ですが、あなたには何もありません」と言ってくれるといいので、待機ループをプランBと呼ぶか、最終的にはそれほど集中的でないものを試してみることができます。

4

2 に答える 2

2

ビットマップメモリ​​はネイティブヒープに割り当てられるため、System.gc()は役に立ちません。ネイティブヒープには独自のGCがありますが、明らかにそれはあなたにとって十分な速さで起動していません-そして私はそれを強制する方法を知りません(つまり、System.gc()のネイティブアナログはありません)。

Nicklas Aがビットマップの再利用を提案しているので、アプリケーションの構造を変更できます。

または、 BitmapFactory OOMで詳しく説明されているネイティブヒープ監視メカニズムを使用して、新しいビットマップを安全に割り当てることができる時期を判断することもできます。

于 2011-07-08T17:19:30.100 に答える
0

System.gc()睡眠の代わりに走ってみてください。


実際、ビットマップはほとんどネイティブコードであるように思われるため、これが役立つかどうかはわかりません。つまり、リサイクルが呼び出されたらすぐにリリースする必要があります。


私には、すべてのUIイベントで新しいビットマップを作成するのは悪い考えのように思えます。1つのビットマップを作成してそれを編集するだけではいけませんか?

于 2011-07-08T17:10:17.790 に答える