2011-07-08 5 views
0

私はBitmapRegionDecoder.decodeRegion(Rect, BitmapFactory.Options)を呼び出すビューアアプリケーションを作成しています。私は以前に各呼び出しの前にdecodeRegionから得たビットマップを廃棄しています:ビットマップがAndroidに完全に配置されているかどうかを確認する方法はありますか?

//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ミリ秒待って、アンドロイドに追いつくのに少し時間を与えます)。

明白な理由から私はこれに満足していません。まず、ガベージコレクションが新しいメモリを割り当てる前に完了していないという私の診断ですか? recycle()コールとカウンタがゼロに滞在した後、第二に、私はカウンターの増分の周り

while(!areaBitmap.isRecycled()) 

を入れてみました。私はisRecycled()を持っているという感覚を見ていますが、代わりにisCompletelyRecycled()メソッドのようなものが必要です。 Androidにこのようなものはありますか?第三に、私はこれでどこにも行くことができない場合は、私の呼び出しが私たちを押し進めるかどうかを知るために使用できる "利用可能なメモリ"方法はありますか?私は1つを見つけることができません。もしAndroidがあなたにはもっと利用可能だとは言えないのなら、私は待っているループをプランBと呼んでもいいし、最終的にはあまり集中力のないものを試してみるのもいいだろう。

答えて

2

ビットマップメモリ​​がネイティブヒープに割り当てられているため、System.gc()は役に立ちません。ネイティブのヒープには独自のGCがありますが、あなたには十分速く足を踏み入れているわけではありません。それを強制する方法は知られていません(System.gc()のネイティブアナログはありません)。

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

または、BitmapFactory OOM driving me nutsに記載されているネイティブヒープ監視メカニズムを使用して、新しいビットマップの割り当てが安全かどうかを判断できます。

+0

ああ、System.gc()はおそらくwait(200)と同じ理由で動作します(遅延が発生します)。私は頻繁に新しいビットマップを作成することを避けることができない理由を述べましたが、私はそれを頻繁にする考えを持っています。記事のメソッドはまさに私が探していたものです。ありがとう! –

+0

私は、ソリューションの特定のBitmapnessを反映するようにタイトルを編集しました。ありがとう! –

0

スリープの代わりにSystem.gc()を実行してみてください。ビットマップは、それは、すぐにリサイクルが呼び出されると解放されなければならないことを意味し、主にネイティブコードのようだとして、これが役立つ場合


は、実際に私はわかりませんよ。私に


あなただけで1つを1つのビットマップを作成および編集ができませんでした、悪いアイデアのように思えるすべてのUIイベントに新しいビットマップを作成するように思えますか?

+0

System.gc()が機能しているようです。しかし、ビットマップを編集することはできません。問題は、ソースビットマップが巨大(2000×3000のようなもの)なので、まずBitmapRegionDecoderを使用する必要があるということです。妥協の解決策があるかもしれません(小さいパン/ズームのリロードを減らすために必要なビットマップよりも少し大きいビットマップ)。 –

+0

ビットマップをあまり頻繁に作成しないようにすることをお勧めします。特に、UI関連の場合は重い操作です。 –

+0

私は信じていません。答えは一般的なメモリよりビットマップに関連しているので、タイトルを編集しました。 –

関連する問題