如题描述,这个问题在项目中存在已久,今天由于自己的功能在首页,初次启动的体验极其糟糕,所以硬下头皮把这个问题解决了。
先来描述一下怎么样一个差的体验吧。就是当我第一次加载网络PNG(当时并不知道是由于这个原因引起的)的时候,就一直显示的是默认的图片,本来按照Fresco的机制是,先显示默认图片,然后去网络加载图片,当图片下载下来就会替换掉原来的默认图片。
感谢https://github.com/facebook/fresco/issues/1803这篇文章让我有了思路。
其实在此之前我已经定位到错误了,我在加载图片的回调里面打了日志,发现没加载出来的图片都走了onFailure方法,抛出了一个异常
IllegalArgumentException Problem decoding into existing bitmap
这个异常是在BitmapFactory.java里面抛出来的,有四个地方抛出,分别是不同的decodeResource,decodeByteArray,decodeStream,decodeFileDescriptor这几个方法抛出的,我们看看其中一个decodeStream吧
public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
if (is == null) {
return null;
}
Bitmap bm = null;
Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeBitmap");
try {
if (is instanceof AssetManager.AssetInputStream) {
final long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
bm = nativeDecodeAsset(asset, outPadding, opts);
} else {
bm = decodeStreamInternal(is, outPadding, opts);
}
if (bm == null && opts != null && opts.inBitmap != null) {
throw new IllegalArgumentException("Problem decoding into existing bitmap");
}
setDensityFromOptions(bm, opts);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
}
return bm;
}
可以看到是在转换bitmap的时候抛出来的。
结合那篇文章可以得出结论是,Fresco在网络加载PNG的时候有一个BUG导致流解析为bitmap的时候抛出异常。
那就解决问题吧。这边我说一下我的解决思路。
第一种方案,就是链接里面说的修改Fresco的源码。可以翻到1.3.0版本的432行,我这里给你找出来了。
public class DecodeProducer implements Producer<CloseableReference<CloseableImage>> {
@Override
protected synchronized boolean updateDecodeJob(EncodedImage encodedImage, boolean isLast) {
boolean ret = super.updateDecodeJob(encodedImage, isLast);
if (!isLast && EncodedImage.isValid(encodedImage) &&
encodedImage.getImageFormat() == DefaultImageFormats.JPEG) {
if (!mProgressiveJpegParser.parseMoreData(encodedImage)) {
return false;
}
int scanNum = mProgressiveJpegParser.getBestScanNumber();
if (scanNum <= mLastScheduledScanNumber) {
return false;
}
if (scanNum < mProgressiveJpegConfig.getNextScanNumberToDecode(mLastScheduledScanNumber)
&& !mProgressiveJpegParser.isEndMarkerRead()) {
return false;
}
mLastScheduledScanNumber = scanNum;
}
return ret;
}
}
把下面这个if里面加上 &&encodedImage.getImageFormat() == DefaultImageFormats.PNG
if (scanNum < mProgressiveJpegConfig.getNextScanNumberToDecode(mLastScheduledScanNumber)
&& !mProgressiveJpegParser.isEndMarkerRead()) {
// We have not reached the minimum scan set by the configuration and there
// are still more scans to be read (the end marker is not reached)
return false;
}
由于现在已经是1.8.0版本的Fresco了,你可以找一下这个类定位到这个地方改。
第二种方案
用反射修改第一个方案里面的这个方法,这可以不修改Fresco的源码
第三种方案,我就是用这个方案的
由于我们App的图片是存在七牛的所以只要在你的Url的后面加上
"?imageView2/1/format/jpg"
把png通过七牛转成jpg,这样就完美解决了。
不过不可能整个app都是用jpg格式的图片,所以可能还是得需要上面两个方案里面的其中一个。如果你有更好的方案,请告诉我一下哈。开源万岁。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)