中断BitmapFactory.decodeStream

时间:2012-08-16 18:55:33

标签: java android multithreading inputstream bitmapfactory

假设我们有一个工作线程,它使用一些连接流调用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,所以如果工作线程终止需要一两秒钟,这不是问题。

谢谢!

2 个答案:

答案 0 :(得分:1)

我认为您可以在UI线程中调用someUnrelatedOptions-> requestCancelDecode()来取消解码,但不能保证取消解码。

Google关键字“bitmapfactory requestCancelDecode decodeStream url openconnection”(不带引号)您可以找到示例代码,例如Android Gallery3D app

此致

陈子腾

答案 1 :(得分:1)

当我在处理非常大的jpeg资产时,关闭Bitmap.decodeStream的输入流时,我在ART上遇到了sigsegv错误。由于使用了非常强大(和易失性)的原生解码器,这个功能非常重要。

我通过首先将输入流包装在BufferedInputStream中,然后将其传递给decodeStream来解决它。

为了可靠地中断decodeStream,请关闭BufferedInputstream(bis):

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

这会立即停止原生解码器,从decodeStream生成一个堆栈跟踪,你可以捕获它(没有崩溃)。

底层问题在于本机解码器,在过早关闭操作之前重置流似乎可以解决与内存相关的崩溃问题。

应该有一种明显的方法来可靠地中断解码器,这需要太过疯狂的实验来解决。希望它能在原生层解决。