美文网首页
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