1

假设我们有一个工作线程,它BitmapFactory.decodeStream使用一些连接流进行调用,如下所示:

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

现在我们需要立即终止该线程以回收BitmapFactory已分配的任何内存。我们不能等待它完成太久,因为 UI 线程需要内存。这个例子被简化了,所以让我们不要详细说明为什么必须这样做。我正在寻找这种方法的解决方案,而不是另一种方法。

我们不能残忍地杀死线程,因为它也在做一些其他的事情,我们有可能会泄露一些东西。唯一干净的方法是使用workerThread.interrupt().

不幸的是,BitmapFactory 并不关心线程是否被中断并继续工作。显然,我正在检查Thread.currentThread().isInterrupted()它存在之后的权利,但这还不够。在非常慢的互联网连接上,加载图像可能需要数年时间,这将冻结应用程序(请记住,UI 线程正在等待)。

所以问题是 - 当线程被中断时我如何BitmapFactory停止?我的想法是包装InputStreamin custom FilterInputStream,覆盖每个函数(实际上并不多),并在每个函数中检查线程是否被中断。如果是,扔一些IOException. BitmapFactory一旦尝试从中提取一些数据,这种方式就会停止InputStream,这应该足够了。有没有更好的方法?如果不是,我应该close()在投掷之前调用流IOException吗?

还有一点注意:正在等待额外内存的 UI 线程正在显示 nice ProgressBar,因此如果工作线程需要一两秒钟才能终止,这不是问题。

谢谢!

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 关键字“bitmapfactory requestCancelDecode decodeStream url openconnection”(不带引号)您可以找到示例代码,例如在Android Gallery3D app中。

问候

陈子腾

于 2012-08-17T02:01:03.253 回答