1

BitmapFactory.decodeStream次のような接続ストリームで呼び出すワーカースレッドがあると仮定します。

Bitmap bitmap = BitmapFactory.decodeStream(new URL(imgUrl).openConnection().getInputStream(), null, someUnrelatedOptions);

BitmapFactory次に、割り当てられたメモリを再利用するために、このスレッドをすぐに終了する必要があります。UIスレッドにメモリが必要なため、終了するのを待つことはできません。例は単純化されているので、なぜこのようにする必要があるのか​​については詳しく説明しません。別のアプローチではなく、このアプローチの解決策を探しています。

スレッドは他のことも行っているので、残酷にスレッドを強制終了することはできません。また、いくつかのものがリークする可能性があります。唯一のクリーンな方法は、を使用することworkerThread.interrupt()です。

残念ながら、BitmapFactoryはスレッドが中断されたかどうかを気にせず、作業を続行します。Thread.currentThread().isInterrupted()明らかに、存在した直後にチェックしていますが、それだけでは不十分です。非常に遅いインターネット接続では、画像の読み込みに数年かかる場合があり、アプリケーションがフリーズします(UIスレッドが待機していることを忘れないでください)。

だから問題は-スレッドが中断されたときにどうやってBitmapFactory停止させるのですか?InputStream私の考えは、カスタムでラップし、FilterInputStreamすべての関数を上書きし(実際には多くはありません)、それぞれでスレッドが中断されているかどうかを確認することです。はいの場合、いくつか投げますIOException。この方法BitmapFactoryは、からデータを取得しようとするとすぐに停止し、InputStream十分なはずです。より良い方法はありますか?close()いいえの場合、スローする前にストリームを呼び出す必要がありIOExceptionますか?

そして少し注意してください:追加のメモリを待っているUIスレッドは素晴らしいを表示しているProgressBarので、ワーカースレッドが終了するのに1〜2秒かかる場合でも問題はありません。

ありがとう!

4

2 に答える 2

2

非常に大きなjpegアセットのネイティブ処理中にBitmap.decodeStreamの入力ストリームを閉じると、ARTでsigsegvエラーが発生していました。この機能は、非常に強力な(そして揮発性の)ネイティブデコーダーを使用しているため、不可欠です。

最初に入力ストリームをBufferedInputStreamでラップし、次にそれをdecodeStreamに渡すことで解決しました。

decodeStreamを確実に中断するには、次のようにBufferedInputstream(bis)を閉じます。

bis.mark(0); //Otto von?
bis.reset();
bis.close();

これにより、ネイティブデコーダーが即座に残酷に停止し、decodeStreamからスタックトレースが生成されます。これをキャッチできます(クラッシュなし)。

根本的な問題はネイティブデコーダーにあり、時期尚早のクローズ操作の前にストリームをリセットすると、メモリ関連のクラッシュが解決されるようです。

デコーダーを確実に中断するための明白な方法があるはずです。これは、回避するにはあまりにも多くの熱狂的な実験を要しました。うまくいけば、それはネイティブレイヤーで解決されるでしょう。

于 2015-10-19T05:04:01.453 に答える
1

デコードをキャンセルすることは保証されていませんが、UIスレッドでsomeUnrelatedOptions-> requestCancelDecode()を呼び出してデコードをキャンセルできると思います。

Googleのキーワード「bitmapfactoryrequestCancelDecodedecodeStreamurl openconnection」(引用符なし)は、AndroidGallery3Dアプリなどでサンプルコードを見つけることができます。

よろしく

Ziteng Chen

于 2012-08-17T02:01:03.253 に答える