當(dāng)Glide搞不定GIF

問題

使用Glide加載圖片Glide.with(context).diskCacheStrategy(DiskCacheStrategy.ALL).into(imageVIew)
注意使用了DiskCacheStrategy.ALL
當(dāng)展示的圖片是GIF的時(shí)候,會(huì)展示很慢疯坤,即使是本地有的圖片浸策,也經(jīng)常會(huì)顯示點(diǎn)位圖較長(zhǎng)時(shí)間才能展示出GIF。
還有一個(gè)條件司倚,就是gif要展示的大小與圖片的大小不一致,需要Glide進(jìn)行縮放。
重現(xiàn)問題方法:加載一個(gè)gif寝殴,使用緩存結(jié)果的磁盤緩存策略,就會(huì)很慢明垢,如果已經(jīng)成功加載過圖片蚣常,可以將緩存的結(jié)果刪除一下嘗試再次重現(xiàn)。

解決

  • 加載的時(shí)候如果可以區(qū)分是gif或者是普通圖片袖外,可以將GIF加載設(shè)置diskCacheStrategySource或者None史隆。
  • 實(shí)際上經(jīng)常加載網(wǎng)絡(luò)的圖片,是通過CDN下載的曼验,只有一個(gè)圖片的Key泌射,在下載完成之前并不知道這是一個(gè)普通圖片還是GIF,所以想如果能將GIF的圖片全部都使用diskCacheStrategySource或者None是不可行的(這樣會(huì)影響普通圖片的展示)鬓照。我們可以hook住GIF在encode的這一步熔酷,直接返回false,就跳過了緩存豺裆。Glide在構(gòu)造完Glide對(duì)象前后都會(huì)向我們回調(diào)拒秘,我們?cè)跇?gòu)造完成glide對(duì)象之后替換掉他的encoder對(duì)象号显,encode方法直接返回false。下面分析原因躺酒,先把解決代碼列出來押蚤。
    @Override
    public void registerComponents(Context context, Glide glide) {
        ResourceEncoder gifEncoder = new ResourceEncoder() {
            @Override
            public boolean encode(Object data, OutputStream os) {
                return false;
            }
            @Override
            public String getId() {
                return "";
            }
        };

        try {
            DataLoadProviderRegistry dataLoadProviderRegistry =
                (DataLoadProviderRegistry) ReflectionUtil.getValue(glide, "dataLoadProviderRegistry");
            if (dataLoadProviderRegistry == null) {
                return;
            }
            DataLoadProvider<ImageVideoWrapper, GifBitmapWrapper> dataLoadProvider =
                dataLoadProviderRegistry.get(ImageVideoWrapper.class, GifBitmapWrapper.class);
            if (dataLoadProvider instanceof ImageVideoGifDrawableLoadProvider) {
                ResourceEncoder<GifBitmapWrapper> encoder = dataLoadProvider.getEncoder();
                if (encoder instanceof GifBitmapWrapperResourceEncoder) {
                    ReflectionUtil.setValue(encoder, "gifEncoder", gifEncoder);
                }
            }
        } catch (Exception e) {
            Log.e("ImageModule", "set gif encoder fail" + e);
        }
    } 

原因

查看源碼發(fā)現(xiàn)glide會(huì)對(duì)gif的每一幀變換的結(jié)果進(jìn)行緩存,重新組成GIF保存下來羹应,實(shí)驗(yàn)的是一個(gè)2M揽碘,124幀的GIF,圖片被放大了3倍园匹,Glide變換后的GIF有54M雳刺。
因?yàn)閱栴}出在了encode的時(shí)候,所以只分析這一部分
DecodeJob中裸违,拿到源圖片之后會(huì)進(jìn)行transform掖桦,然后將結(jié)果緩存起來

變換并存儲(chǔ)

可以看到如果我們不設(shè)置緩存result的話就不會(huì)存儲(chǔ),就不會(huì)有問題供汛,將encoder和轉(zhuǎn)換之后的resource都傳給了writer
判斷緩存策略枪汪,構(gòu)造writer進(jìn)行緩存

Writerwrite方法就是將圖片寫到DiskLRUCache
使用Encoder進(jìn)行重新編碼再存儲(chǔ)

此時(shí)的encoder是GifBitmapWrapperResourceEncoder對(duì)象,看它的encode方法怔昨,第一次decode GIF的時(shí)候會(huì)走else分支
GIF的EncoderWrapper

上面的gifEncoderGifResourceEncoder的對(duì)象料饥,可以看到重新解析了GIF,實(shí)際上之前已經(jīng)解析過一遍了)朱监,對(duì)每一幀都要進(jìn)行變換岸啡,encoderaddFrame對(duì)第一幀進(jìn)行了存儲(chǔ)。

真正對(duì)GIF重新編碼的地方

還好Glide有bitmap池赫编,內(nèi)存不會(huì)抖動(dòng)巡蘸,不過想想如果圖片有個(gè)100多幀甚至幾百幀,這個(gè)過程肯定是耗時(shí)的擂送,而且我們從前面的transform開始到encode都是同步調(diào)用悦荒,不存儲(chǔ)完成是無法走下去繼續(xù)展示的。如果不對(duì)圖片進(jìn)行縮放的話不用走這個(gè)encode嘹吨,也就不會(huì)慢搬味。

上面的代碼我們也可以看到最終使用了gifEncoder這個(gè)成員,我們只要將GifBitmapWrapperResourceEncoder這個(gè)成員換掉就可以了蟀拷。
而這個(gè)encoder是構(gòu)造glide的時(shí)候就已經(jīng)設(shè)置進(jìn)去了碰纬,并且不會(huì)再更改,所以是我們理想的hook點(diǎn)

Glide構(gòu)造

注意

使用glide3.7
因?yàn)槭褂昧朔瓷湮史遥獙?duì)反射的類進(jìn)行keep

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末悦析,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子此衅,更是在濱河造成了極大的恐慌强戴,老刑警劉巖亭螟,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異骑歹,居然都是意外死亡预烙,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門道媚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來默伍,“玉大人,你說我怎么就攤上這事衰琐。” “怎么了炼蹦?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵羡宙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我掐隐,道長(zhǎng)狗热,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任虑省,我火速辦了婚禮匿刮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘探颈。我一直安慰自己熟丸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布伪节。 她就那樣靜靜地躺著光羞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怀大。 梳的紋絲不亂的頭發(fā)上纱兑,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音化借,去河邊找鬼潜慎。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蓖康,可吹牛的內(nèi)容都是我干的铐炫。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼蒜焊,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼驳遵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起山涡,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤堤结,失蹤者是張志新(化名)和其女友劉穎唆迁,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體竞穷,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡唐责,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瘾带。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鼠哥。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖看政,靈堂內(nèi)的尸體忽然破棺而出朴恳,到底是詐尸還是另有隱情,我是刑警寧澤允蚣,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布于颖,位于F島的核電站,受9級(jí)特大地震影響嚷兔,放射性物質(zhì)發(fā)生泄漏森渐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一冒晰、第九天 我趴在偏房一處隱蔽的房頂上張望同衣。 院中可真熱鬧,春花似錦壶运、人聲如沸耐齐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蚪缀。三九已至,卻和暖如春恕出,著一層夾襖步出監(jiān)牢的瞬間询枚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工浙巫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留金蜀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓的畴,卻偏偏與公主長(zhǎng)得像渊抄,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子丧裁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 一护桦、簡(jiǎn)介 在泰國(guó)舉行的谷歌開發(fā)者論壇上,谷歌為我們介紹了一個(gè)名叫Glide的圖片加載庫(kù)煎娇,作者是bumptech二庵。這...
    天天大保建閱讀 7,453評(píng)論 2 28
  • 學(xué)習(xí)來源:郭霖大師博客地址 1贪染、圖片加載框架挺多,如Volley催享、Glide杭隙、Picasso、Fresco因妙、本次是...
    子謙寶寶閱讀 1,743評(píng)論 0 6
  • Glide筆記 一痰憎、簡(jiǎn)介 在泰國(guó)舉行的谷歌開發(fā)者論壇上,谷歌為我們介紹了一個(gè)名叫Glide的圖片加載庫(kù)攀涵,作者是bu...
    AndroidMaster閱讀 3,870評(píng)論 0 27
  • 公司:寧波大發(fā)化纖有限公司 姓名:馮玉停 期數(shù):六項(xiàng)精進(jìn)224期感謝二組學(xué)員铣耘,234期感謝三組志工,260期感謝一...
    塵埃wyzh閱讀 91評(píng)論 0 0
  • 親愛的兒子,每天下班回家的路上据德,我都給自己悄悄地上課——今天別跟兒子發(fā)飆!心平氣和地輔導(dǎo)作業(yè)跷车,查漏補(bǔ)缺棘利!可...
    在水一方青花瓷閱讀 895評(píng)論 5 6