Fresco加載gif不能顯示問(wèn)題解決

1.Fresco引發(fā)的血案

前面寫過(guò)一篇關(guān)于Fresco分析的文章,沒(méi)想到?jīng)]過(guò)幾天就發(fā)生了一場(chǎng)血案。事情是這樣的,昨天另一個(gè)小哥跟我說(shuō)他用Fresco加載gif不能顯示了,他也不知道為什么,也沒(méi)改什么東西,讓我?guī)兔匆幌?。其?shí)我們項(xiàng)目用Fresco已經(jīng)挺久的了,然后之前那個(gè)地方也沒(méi)有問(wèn)題,但是不知道為什么就是不顯示了。于是今天就開始了折騰。

2.解決過(guò)程

1.首先我懷疑是不是改了布局,導(dǎo)致控件沒(méi)有顯示出來(lái)。帶著這樣的懷疑,我設(shè)置了控件的背景為鮮明的紅色,發(fā)現(xiàn)是顯示出來(lái)的,并沒(méi)有什么問(wèn)題。當(dāng)然這個(gè)想法可能太簡(jiǎn)單了點(diǎn),但是這樣的原因也是很有可能的,所以當(dāng)一個(gè)控件不能顯示的時(shí)候,你一定要先確定改控件是不是Visible,如果是Visible那么再去找其他原因。

2.懷疑加載圖片的URI有問(wèn)題,通過(guò)跟蹤AbstractDraweeController中的
submitRequest()方向作為入口,不斷跟蹤到如下圖的地方,發(fā)現(xiàn)URI正確,且正確調(diào)用的相應(yīng)的方法。


這里寫圖片描述

既然url沒(méi)有錯(cuò),那我看看submit中的回調(diào)吧,如下圖,媽蛋居然調(diào)的是失敗,這我就懵逼了,這tm到底哪里出錯(cuò)了呢,就錯(cuò)了也不是咱自己的錯(cuò)吧,這鍋不得facebook來(lái)背嗎?但以我多年的職業(yè)經(jīng)驗(yàn)來(lái)看這個(gè)事情不是那么簡(jiǎn)單,于是我繼續(xù)斷點(diǎn)反復(fù)查看。我們通過(guò)對(duì)Fresco的分析會(huì)發(fā)現(xiàn),最終在處理請(qǐng)求時(shí)都會(huì)調(diào)用Producer類中的的produceResults來(lái)消費(fèi)請(qǐng)求,但是對(duì)于這個(gè)Producer我也不是很懂,但是就憑他要調(diào)用的這個(gè)方法,我斷點(diǎn)逐行分析,發(fā)現(xiàn)并沒(méi)有什么問(wèn)題。最終個(gè)條路也只能到這里結(jié)束。


這里寫圖片描述

3.實(shí)在沒(méi)什么頭緒了,于是去查看Fresco的文檔http://www.fresco-cn.org/docs/getting-started.html,文檔中關(guān)于加載gif的描述如下:

Uri uri;
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.setAutoPlayAnimations(true)
. // 其他設(shè)置(如果有的話)
.build();
mSimpleDraweeView.setController(controller);

這代碼這么簡(jiǎn)單沒(méi)什么問(wèn)題啊。繼續(xù)看文檔,發(fā)現(xiàn)在問(wèn)題處理中說(shuō)可以啟動(dòng)日志,既然沒(méi)有辦法那就啟動(dòng)日志來(lái)看看唄。Fresco日志默認(rèn)是關(guān)閉的,啟動(dòng)日志方法如下,在Fresco初始化時(shí)做如下配置:

Set<RequestListener> requestListeners = new HashSet<>();
requestListeners.add(new RequestLoggingListener());
ImagePipelineConfig config = ImagePipelineConfig.newBuilder(context)
// other setters
.setRequestListeners(requestListeners)
.build();
Fresco.initialize(context, config);
FLog.setMinimumLoggingLevel(FLog.VERBOSE);

查看日志方法如下:

adb logcat -v threadtime | grep -iE 'LoggingListener|AbstractDraweeController|BufferedDiskCache'

ok打開日志后,再次加載,看到如下日志:


這里寫圖片描述

什么意思呢?大概就是在DecodeProducer中有一個(gè)空指針異常,調(diào)用了decodeGif在一個(gè)空引用上。于是查看DecodeProducer類找到doDecode方法,發(fā)現(xiàn)其中調(diào)用了mImageDecoder.decodeImage,繼續(xù)查看在decodeImage中調(diào)用到了我們要找的decodeGif方法,內(nèi)容如下:


這里寫圖片描述

根據(jù)這個(gè)方法再打斷點(diǎn)說(shuō)的就是這個(gè)mAnimatedImageFactory是空指針,那么這個(gè)AnimatedImageFactory是個(gè)什么鬼,從源碼我可以知道這個(gè)類就是用來(lái)解析動(dòng)圖的,目前可以解析gif和webP。 繼續(xù)查看調(diào)用可以看到這個(gè)factory是在ImagePipeline中創(chuàng)建的,如下:
這里寫圖片描述

就是在這里通過(guò)AnimatedFactoryProvider創(chuàng)建了一個(gè)AnimatedFactory,里面代碼如下:


這里寫圖片描述

通過(guò)反射來(lái)創(chuàng)建的,既然出現(xiàn)了空指針那就是這里創(chuàng)建的問(wèn)題咯,那我們來(lái)看看這個(gè)兩個(gè)類,發(fā)現(xiàn)根本找不到,所以問(wèn)題就是這里咯。同時(shí)發(fā)現(xiàn)在項(xiàng)目中存在兩個(gè)Fresco的包0.8.0和0.11.0,于是定位到可能是依賴沖突的原因。查看了0.8.0里面創(chuàng)建AnimatedFactory的代碼發(fā)現(xiàn)與0.11.0中的代碼還是有點(diǎn)區(qū)別的,確認(rèn)是依賴包沖突的問(wèn)題了。
這里寫圖片描述

通過(guò)在Android studio Terminal輸入如下命令gradlew -q app:dependencies查看當(dāng)前使用的依賴版本,發(fā)現(xiàn)雖然配置的是使用0.8.0但是實(shí)際使用的卻是0.11.0。所以解決辦法1就是恢復(fù)到0.8.0版本,至于11版本的為什么沒(méi)有那兩個(gè)類我們稍后再來(lái)看。

+--- com.facebook.fresco:fresco:0.8.0 -> 0.11.0
|    +--- com.facebook.fresco:drawee:0.11.0
|    |    +--- com.android.support:support-v4:23.2.1 (*)
|    |    \--- com.facebook.fresco:fbcore:0.11.0
|    +--- com.facebook.fresco:fbcore:0.11.0
|    \--- com.facebook.fresco:imagepipeline:0.11.0
|         +--- com.android.support:support-v4:23.2.1 (*)
|         +--- com.facebook.fresco:fbcore:0.11.0
|         +--- com.parse.bolts:bolts-tasks:1.4.0
|         +--- com.nineoldandroids:library:2.4.0
|         \--- com.facebook.fresco:imagepipeline-base:0.11.0
|              +--- com.android.support:support-v4:23.2.1 (*)
|              +--- com.facebook.fresco:fbcore:0.11.0
|              +--- com.parse.bolts:bolts-tasks:1.4.0
|              \--- com.nineoldandroids:library:2.4.0

+--- com.facebook.react:react-native:0.29.2
|    +--- com.google.code.findbugs:jsr305:3.0.0
|    +--- org.webkit:android-jsc:r174650
|    +--- com.facebook.fresco:imagepipeline-okhttp3:0.11.0
|    |    +--- com.facebook.fresco:fbcore:0.11.0
|    |    +--- com.squareup.okhttp3:okhttp:3.0.1 -> 3.2.0
|    |    |    \--- com.squareup.okio:okio:1.6.0 -> 1.8.0
|    |    \--- com.facebook.fresco:imagepipeline:0.11.0 (*)
|    +--- com.squareup.okio:okio:1.8.0
|    +--- com.fasterxml.jackson.core:jackson-core:2.2.3
|    +--- com.squareup.okhttp3:okhttp:3.2.0 (*)
|    +--- com.facebook.fresco:fresco:0.11.0 (*)
|    +--- com.squareup.okhttp3:okhttp-ws:3.2.0
|    |    \--- com.squareup.okhttp3:okhttp:3.2.0 (*)
|    +--- com.android.support:recyclerview-v7:23.0.1 (*)
|    +--- com.squareup.okhttp3:okhttp-urlconnection:3.2.0
|    |    \--- com.squareup.okhttp3:okhttp:3.2.0 (*)
|    \--- com.android.support:appcompat-v7:23.0.1 (*)

從上面的依賴關(guān)系可以看出我們自己依賴了fresco的0.8,同時(shí)依賴了react,但是react中依賴了fresco 0.11導(dǎo)致我們實(shí)際依賴的是搞版本的fresco,所以如果要使用低版本的,按理說(shuō)只需要把react中的fresco排除,然后我們?cè)趯?dǎo)入自己需要的版本就行了,但是我按照這樣的思路在build.gradle進(jìn)行了如下配置,結(jié)果還是使用11版本的,最終沒(méi)有找到原因,你們也可以試一下,如果有發(fā)現(xiàn)什么問(wèn)題的一定要告訴我。

compile 'com.facebook.fresco:fresco:0.8.0'
compile ('com.facebook.react:react-native:0.29.2') {
   exclude module:'com.facebook.fresco:fresco'
}

接下來(lái)我們就來(lái)看看為什么使用11版本的就少了那兩個(gè)類呢?查閱各種資料,最終在一篇博客中發(fā)現(xiàn)了如下的內(nèi)容:

一定要導(dǎo)入下邊這個(gè) compile 'com.facebook.fresco:animated-gif:0.12.0',否則gif圖壓根不動(dòng)

于是瞬間懂了,原來(lái)高版本的fresco把gif相關(guān)的內(nèi)容獨(dú)立到了另一個(gè)依賴?yán)锩妫@樣如果不需要用到gif的項(xiàng)目就不需要導(dǎo)入,由于我們升級(jí)到了高版本,所以默認(rèn)是沒(méi)有g(shù)if相關(guān)的類的,所以就缺少了那兩個(gè)類,導(dǎo)致gif不能顯示,于是導(dǎo)入后,完美解決問(wèn)題。

3.總結(jié)

解決問(wèn)題的方法有兩種:
1.退回到低版本的fresco
2.使用高版本的,需要另外導(dǎo)入com.facebook.fresco:animated-gif這個(gè)依賴

參考資料
gradle 管理依賴庫(kù)兩個(gè)問(wèn)題
fesco加載gif類似問(wèn)題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,361評(píng)論 25 708
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,711評(píng)論 19 139
  • 圖片加載是Andriod開發(fā)幾乎所有應(yīng)用都需要用到,做Android開發(fā)的朋友或多或少都遇到過(guò)由于圖片加載過(guò)多導(dǎo)致...
    磨礪營(yíng)IT閱讀 2,905評(píng)論 -1 8
  • Fresco簡(jiǎn)單的使用—SimpleDraweeView 百學(xué)須先立志—學(xué)前須知: 在我們平時(shí)加載圖片(不管是下載...
    天天大保建閱讀 3,551評(píng)論 0 8
  • 在這個(gè)世界 有好多人的名字寫在天空上 它們像星星一樣閃耀 像云朵一樣纏綿 也像雷電一樣驚魂 當(dāng)然,還有一些重復(fù)的名...
    甘肅子溪閱讀 328評(píng)論 0 5

友情鏈接更多精彩內(nèi)容