美文网首页
Glide对Problem decoding into exis

Glide对Problem decoding into exis

作者: vb12 | 来源:发表于2018-07-10 21:41 被阅读250次

按照预期, glide对任何bitmap的使用, 都需要经由LruBitmapPool生成.
但是最近在调试代码的时候, 也发现了一些异常的现象:
明明bitmapPool借出bitmap对象的时候, 尺寸大小是a, 但是后面归还给bitmapPool的对象尺寸却出现了b大小.
这很让人费解.

调试了一晚上, 才发现, 由于有些图片本身格式有问题, 比如不完整. 会导致在Downsampler.java中的decodeStream()中出现异常.

private static Bitmap decodeStream(InputStream is, BitmapFactory.Options options,
      DecodeCallbacks callbacks, BitmapPool bitmapPool) throws IOException {
    if (options.inJustDecodeBounds) {
      is.mark(MARK_POSITION);
    } else {
      // Once we've read the image header, we no longer need to allow the buffer to expand in
      // size. To avoid unnecessary allocations reading image data, we fix the mark limit so that it
      // is no larger than our current buffer size here. We need to do so immediately before
      // decoding the full image to avoid having our mark limit overridden by other calls to
      // mark and reset. See issue #225.
      callbacks.onObtainBounds();
    }
    // BitmapFactory.Options out* variables are reset by most calls to decodeStream, successful or
    // otherwise, so capture here in case we log below.
    int sourceWidth = options.outWidth;
    int sourceHeight = options.outHeight;
    String outMimeType = options.outMimeType;
    final Bitmap result;
    TransformationUtils.getBitmapDrawableLock().lock();
    try {
      result = BitmapFactory.decodeStream(is, null, options);
    } catch (IllegalArgumentException e) {
      IOException bitmapAssertionException =
          newIoExceptionForInBitmapAssertion(e, sourceWidth, sourceHeight, outMimeType, options);
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "Failed to decode with inBitmap, trying again without Bitmap re-use",
            bitmapAssertionException);
      }
      if (options.inBitmap != null) {
        try {
          is.reset();
          bitmapPool.put(options.inBitmap);
          options.inBitmap = null;
          return decodeStream(is, options, callbacks, bitmapPool);
        } catch (IOException resetException) {
          throw bitmapAssertionException;
        }
      }
      throw bitmapAssertionException;
    } finally {
      TransformationUtils.getBitmapDrawableLock().unlock();
    }

    if (options.inJustDecodeBounds) {
      is.reset();

    }
    return result;
  }

注意上面的那个catch()分支, 如果进入之后, 会把之前从bitmapPool中借出的bitmap对象( options.inBitmap) 归还. 然后继续重新加载图片, 这是这次加载, 就是纯新建的bitmap了, 不是bitmapPool中的对象了.

而后续的流程, 并不知晓这个情况, 导致会在某个节点, 仍然把此处新生成的bitmap对象, 归还给bitmapPool.
于是就出现了开头所说的现象.
这里列出具体的exception:
07-10 21:07:33.987 8694-9208/com.sogou.luedong E/Downsampler: decodeStream:
java.lang.IllegalArgumentException: Problem decoding into existing bitmap

从网上查, 也能查到很多关于这个报错的问题:
https://stackoverflow.com/questions/16034756/why-does-decoding-bitmap-with-inbitmap-always-get-java-lang-illegalargumentexcep
https://github.com/facebook/fresco/issues/1204

想了想, 也并没有什么更好的办法解决, 对于出现异常之后的这种流程, 既然bitmap已经新生成了, 放入bitmapPool是最好的选择. 因为后续保不齐就真的能用到.

也许只能从后台数据上下功夫, 去除此类图片. 多半是由于抓取时有问题, 没有抓取完整.

相关文章

网友评论

      本文标题:Glide对Problem decoding into exis

      本文链接:https://www.haomeiwen.com/subject/denqpftx.html