假设我们有一个工作线程,它使用一些连接流调用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
,所以如果工作线程终止需要一两秒钟,这不是问题。
谢谢!
答案 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生成一个堆栈跟踪,你可以捕获它(没有崩溃)。
底层问题在于本机解码器,在过早关闭操作之前重置流似乎可以解决与内存相关的崩溃问题。
应该有一种明显的方法来可靠地中断解码器,这需要太过疯狂的实验来解决。希望它能在原生层解决。