按照預期, glide對任何bitmap的使用, 都需要經由LruBitmapPool生成.
但是最近在調試代碼的時候, 也發(fā)現(xiàn)了一些異常的現(xiàn)象:
明明bitmapPool借出bitmap對象的時候, 尺寸大小是a, 但是后面歸還給bitmapPool的對象尺寸卻出現(xiàn)了b大小.
這很讓人費解.
調試了一晚上, 才發(fā)現(xiàn), 由于有些圖片本身格式有問題, 比如不完整. 會導致在Downsampler.java中的decodeStream()中出現(xiàn)異常.
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) 歸還. 然后繼續(xù)重新加載圖片, 這是這次加載, 就是純新建的bitmap了, 不是bitmapPool中的對象了.
而后續(xù)的流程, 并不知曉這個情況, 導致會在某個節(jié)點, 仍然把此處新生成的bitmap對象, 歸還給bitmapPool.
于是就出現(xiàn)了開頭所說的現(xiàn)象.
這里列出具體的exception:
07-10 21:07:33.987 8694-9208/com.sogou.luedong E/Downsampler: decodeStream:
java.lang.IllegalArgumentException: Problem decoding into existing bitmap
從網(wǎng)上查, 也能查到很多關于這個報錯的問題:
https://stackoverflow.com/questions/16034756/why-does-decoding-bitmap-with-inbitmap-always-get-java-lang-illegalargumentexcep
https://github.com/facebook/fresco/issues/1204
想了想, 也并沒有什么更好的辦法解決, 對于出現(xiàn)異常之后的這種流程, 既然bitmap已經新生成了, 放入bitmapPool是最好的選擇. 因為后續(xù)保不齊就真的能用到.
也許只能從后臺數(shù)據(jù)上下功夫, 去除此類圖片. 多半是由于抓取時有問題, 沒有抓取完整.