3

12-21 11:01:14.045: E/AndroidRuntime(6819): java.lang.RuntimeException: Canvas: 试图使用回收的位图 android.graphics.Bitmap@4180103 12-21 11:01:14.045: E/AndroidRuntime( 6819): 在 android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1084) 12-21 11:01:14.045: E/AndroidRuntime(6819): 在 android.view.GLES20Canvas.drawBitmap(GLES20Canvas.java:844) 12 -21 11:01:14.045: E/AndroidRuntime(6819): 在 android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:490) 12-21 11:01:14.045: E/AndroidRuntime(6819): 在 android .widget.ImageView.onDraw(ImageView.java:1037) 12-21 11:01:14.045: E/AndroidRuntime(6819): 在 android.view.View.draw(View.java:14465) 12-21 11:01 :14.045: E/AndroidRuntime(6819): 在 android.view.View.getDisplayList(View.java:13362) 12-21 11:01:14.045: E/AndroidRuntime(6819): 在 android.view.View。getDisplayList(View.java:13404) 12-21 11:01:14.045: E/AndroidRuntime(6819): 在 android.view.View.draw(View.java:14182) 12-21 11:01:14.045: E/ AndroidRuntime(6819): 在 android.view.ViewGroup.drawChild(ViewGroup.java:3103) 12-21 11:01:14.045: E/AndroidRuntime(6819): 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:2940 ) 12-21 11:01:14.045: E/AndroidRuntime(6819): 在 android.widget.AbsListView.dispatchDraw(AbsListView.java:2458)dispatchDraw(AbsListView.java:2458)dispatchDraw(AbsListView.java:2458)

我建立了一个新类并使其扩展BasePostprocessor,我什么都不做。但是当它运行时,示例会抛出上述异常;我只是imagepipeline用来下载图像,不要使用simpledraweeview.

com.facebook.imagepipeline.request.ImageRequestBuilder requestBuilder=   com.facebook.imagepipeline.request.ImageRequestBuilder
.newBuilderWithSource(uri);

if (imageRequest.getTargetWidth() > 0 && imageRequest.getTargetHeight()  > 0) {
    requestBuilder.setResizeOptions(new com.facebook.imagepipeline.common.ResizeOptions(imageRequest
            .getTargetWidth(), imageRequest.getTargetHeight()));
}

requestBuilder.setAutoRotateEnabled(true);
requestBuilder.setPostprocessor(new FPostProcessor(getImageConfig()));
public class FPostProcessor extends BasePostprocessor{
private FImageConfig mImageConfig;

public FPostProcessor(FImageConfig imageConfig){
    mImageConfig = imageConfig;
}
/*
@Override
public CloseableReference<Bitmap> process(Bitmap sourceBitmap,    PlatformBitmapFactory bitmapFactory) {
return super.process(sourceBitmap, bitmapFactory);
}*/
}
4

1 回答 1

0

我认为这与后处理器无关。如果您不使用 Drawee,而是直接使用 imagepipeline,则需要非常小心处理图像的方式。您应该阅读有关如何直接使用 imagepipeline的文档。

我怀疑您是ClsoeableReference<CloseableImage>从管道中获取的,然后您只需将位图从中取出并忘记ClsoeableReference. 这是错误的做法。一旦ClsoeableReference超出范围,它将变得容易被垃圾收集,并且当 GC 发生时,底层位图可能会被回收。即使您BaseBitmapDataSubscriber直接使用提供 Bitmap 的情况也是如此。文档中也详细介绍了这一点。

您使用后处理器而不是没有后处理器遇到这种情况的最可能原因是,在前一种情况下,位图缓存可能会使您的位图保持活动状态。使用您的后处理器,这不会发生,因为它没有启用缓存。

换句话说,管道返回一个ClsoeableReference<CloseableImage> R1用. 将有另一个包装相同的内容保存在位图缓存中,直到稍后缓存决定驱逐该图像。由于缓存和您都有对该图像的引用,因此它的引用计数为 2。即使您不遵守 Fresco API 并且让垃圾收集,引用计数也只会下降到 1,因为缓存仍然包含它记忆。但是,您不应该依赖它。那是没有后处理器。CloseableImage IBitmap BCloseableReference R2CloseableImage ICloseableReference R1

如果您指定后处理器,则会发生一些稍微不同的事情。管道现在将缓存原始文件CloseableImage I1Bitmap B1但将返回一个CloseableImage I2的后处理文件Bitmap B2。由于您的后处理器没有启用缓存,您将是引用的唯一持有者,I2这一次如果您让它被垃圾收集,您将留下一个回收的位图,因为没有缓存来隐藏问题。

需要明确的是,正确的解决方案是不启用后处理器缓存!正确的解决方案是正确处理CloseableReference管道返回的内容,如文档中所述。

如果不提供有关如何使用管道的实际代码,我无法确定,但这很可能是发生的情况。

于 2016-01-27T19:10:39.307 回答