Fresco内部非難による初のネットワークからのPNG画像のロードに失敗

6608 ワード

問題の説明のように、この問題はプロジェクトの中で長い間存在していたが、今日は自分の機能がトップページにあるため、初めて起動した体験が極めて悪いので、無理にこの問題を解決した.まず、どのような悪い体験を説明しましょう.つまり、私が初めてネットワークPNGをロードしたとき(その理由が分からなかった)、ずっとデフォルトの画像が表示されていましたが、もともとFrescoのメカニズムでは、まずデフォルトの画像を表示し、それからネットワークに行って画像をロードし、画像がダウンロードされると元のデフォルトの画像を置き換えます.
に感謝https://github.com/facebook/fresco/issues/1803この文章は私に考えを持たせた.
実はその前に私はすでに间违った位置に着いて、私は画像のコールバックの中でログを打って、ロードしていない画像がすべてonFailureの方法を歩いたことを発见して、1つの异常を投げ出しました
IllegalArgumentException Problem decoding into existing bitmap

この異常はBitmapFactoryでJAvaの中から投げ出されたのは、4つの場所で投げ出されています.それぞれ異なるdecodeResource、decodeByteArray、decodeStream、decodeFileDescriptorのいくつかの方法で投げ出されています.その中の1つのdecodeStreamを見てみましょう.
public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
        // we don't throw in this case, thus allowing the caller to only check
        // the cache, and not force the image to be decoded.
        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がビットマップとしてストリームを解析したときに異常を投げ出すと結論した.
では、問題を解決しましょう.ここで私の解決策を話します.
1つ目の案は、リンクの中で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) {
              // We have already decoded this scan, no need to do so again
              return false;
            }
            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;
            }
            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なので、このクラスを探してこの場所に変更することができます.
第2のスキームは反射で第1のスキームの中のこの方法を修正して、これはFrescoのソースコードを修正しないことができます
3つ目の案は、私はこの案を使っています.私たちのAppの画像は7牛が存在しているので、あなたのUrlの後ろに追加すればいいです.
"?imageView2/1/format/jpg"

pngを七牛でjpgに変えることで完璧に解決しました.しかし、app全体がjpg形式の画像であることは不可能なので、上記の2つのスキームのうちの1つが必要かもしれません.もっといい案があれば、教えてください.開源万歳.