Glide ‘優(yōu)’ 與 ‘愁’

隨著業(yè)務(wù)的增長(zhǎng),加載圖片是不可避免的需求。從一開始的自己寫一個(gè) ImageLoader 到井噴似的第三方圖片加載庫(kù),當(dāng)然中間還時(shí)不時(shí)穿插著 asynctask ,三級(jí)緩存,LRU Cache等。那個(gè)時(shí)候想必大家都用過 nostra13/Android-Universal-Image-Loader , 大家都紛紛擁抱了它,確實(shí)時(shí)勢(shì)造英雄吧,所以我很欽佩作者。但三年前作者大概可能覺得實(shí)在是太累了的,宣布不再維護(hù)了的。在此期間也有一些優(yōu)秀的開源庫(kù)比如 square 出來(lái)的 Picasso ,優(yōu)雅的鏈?zhǔn)秸{(diào)用想必很多人選擇了擁抱他。后來(lái)Google在2014年的google I/O大會(huì)上發(fā)布的官方app中使用的 bumptech/glide 闖入大家的視野, Google 推薦大家圖片加載使用 Glide. 當(dāng)然 Glide 的使用方式也是仿照 Picasso 。所以幾乎沒有任何遷移成本,很多人也開始擁抱了 Glide. 當(dāng)然在此期間 Facebook 也不甘寂寞橫空出來(lái)開源了 fresco 。

為什么會(huì)選擇 Glide

為什么選擇 Glide ,前言中也提到了 畢竟是 Google 推薦的最佳選擇。除此之外也可以做一下簡(jiǎn)單的對(duì)比

Glide VS Picasso

雙胞胎兄弟之間的對(duì)比,使用方式相同,但 Glide 之所以勝出,不僅僅是 Google的推薦,更多應(yīng)該歸功于 GIF 的支持。 在沒有 Glide 之前,常用的做法就是寫了個(gè)自定義 view 然后 用一個(gè) media 去播放。有了 Glide 之后幾乎對(duì)于 GIF 無(wú)感知了的, 內(nèi)部已經(jīng)支持了的。可以像普通圖片那樣去加載并且顯示出來(lái)動(dòng)圖。

Glide VS Android-Universal-Image-Loader

雖然有再多的不舍,一個(gè)已經(jīng)不再維護(hù)的開源庫(kù),Android碎片化那么嚴(yán)重,我們自己維護(hù)起來(lái)還是要考慮成本的。所以 Glide 勝出。

Glide VS fresco

兩個(gè)都支持 GIF。所以 GIF 這一關(guān)pass掉。說到這里不得不提到一個(gè)頭疼的OOM問題,fresco 之所以很快闖入大家的視線,大概就是因?yàn)?Facebook 說他們使用了 native 內(nèi)存規(guī)避掉了 OutOfMemoryError 問題。而且官方還專門寫了個(gè)demo,把幾大流行的開源庫(kù)都集成進(jìn)去,為了說明自己的圖片加載庫(kù)加載同樣的圖片速度更快,內(nèi)存占用更低。所以 fresco 相比較于 Glide 的(官方)優(yōu)勢(shì)就是這兩點(diǎn): 內(nèi)存以及加載速度。但是我為什么依舊堅(jiān)持拋棄了 fresco ?

  1. “ In Android 4.x and lower, Fresco puts images in a special region of Android memory. This lets your application run faster - and suffer the dreaded OutOfMemoryError much less often.” 官方的原話是這么說的,所以在高版本上面依舊使用的Java 內(nèi)存,所以不可避免依舊會(huì)占用內(nèi)存。

  2. 提到內(nèi)存,不得不說到另外一個(gè)笑話,fresco 最大只支持圖片文件大小為 2M 。記得有一次幫其他團(tuán)隊(duì)跟蹤問題,看到了 fresco 源碼中有一個(gè) 最大 size 2M 常量 。于是當(dāng)場(chǎng)找了一個(gè)10M的圖片作為測(cè)試。 Glide 正常顯示, fresco顯示黑屏。。。

  3. 使用方式上,fresco 推薦的是用他提供的 SimpleDraweeView . 這個(gè)方式意味著我們的遷移成本會(huì)非常的高,要改布局文件,其次還必須給定大?。ɑ蛘弑壤?當(dāng)然他也支持代碼來(lái)加載圖片,比如 DraweeHierarchy,但是寫起來(lái)還是真心很費(fèi)勁的,很不友好,改動(dòng)成本居高。

  4. fresco 更多是native實(shí)現(xiàn)。所以需要對(duì)NDK有所了解,但個(gè)人對(duì)NDK不太了解,相比較于 Glide, 同樣遇到問題之后,修改源碼的成本,Glide 成本更可控。前者可能就不太好下手了的。

  5. Glide 各種 BitmapTransformation,比如圓形,圓角等,更讓人喜歡。

  6. 這一點(diǎn)就當(dāng)隨意吐槽一下,當(dāng)然也可以說心疼一下 Facebook。因?yàn)樵跊]有 Android studio (gradle構(gòu)建)的情況下,想必大家都用的是 eclipse 吧。那么就意味著 fresco 得提供 Jar 包. 這一點(diǎn)當(dāng)時(shí)也是把很多人拒之門外了的,可笑的是當(dāng) Facebook 費(fèi)了老大勁的搞出來(lái) jar 包之后,大家早就紛紛轉(zhuǎn)戰(zhàn) gradle 構(gòu)建工程, 直接 maven 依賴?yán)?。大寫的尷尬?/p>

綜上所述,Glide 依舊勝出。

Glide 是如何解決圖片加載生命周期的?(精髓之一)(也是bug高發(fā)地帶)

當(dāng)一個(gè)界面離開之后,我們更希望當(dāng)前的圖片取消加載,那么 Glide 是怎么做到的呢?

Glide 的使用方式上,一定需要傳入一個(gè) context 給它。它為什么需要拿上下文呢?原因就是可以根據(jù)不同的上下文進(jìn)行處理,拿到 context (除了application context)之后,Glide做了一件很巧妙的事情,就是在這個(gè)界面上追加一個(gè) fragment,由于 fragment 添加到了 activity 上,是可以捕獲到生命周期的,因此可以在 destroy 的時(shí)候取消掉當(dāng)前context下的 glide對(duì)象中的加載任務(wù)。

為什么標(biāo)題后面說是 ‘也是bug高發(fā)地帶’ 呢? 因?yàn)閺膶?shí)現(xiàn)方式上,它是巧妙的利用了fragment的生命周期來(lái)實(shí)現(xiàn)的‘銷毀’動(dòng)作,那么就類似于另外一個(gè)高發(fā)bug,延時(shí)的匿名內(nèi)部類(網(wǎng)絡(luò)請(qǐng)求callback回來(lái)),界面已經(jīng)銷毀,所以當(dāng)前activity依附的glide也就銷毀了的,此時(shí)再嘗試加載圖片的話,就會(huì)crash。具體源碼中可以看到這里:

https://github.com/bumptech/glide/blob/master/library/src/main/java/com/bumptech/glide/Glide.java

 @NonNull
 private static RequestManagerRetriever getRetriever(@Nullable Context context) {
   // Context could be null for other reasons (ie the user passes in null), but in practice it will
   // only occur due to errors with the Fragment lifecycle.
   Preconditions.checkNotNull(
       context,
       "You cannot start a load on a not yet attached View or a Fragment where getActivity() "
           + "returns null (which usually occurs when getActivity() is called before the Fragment "
           + "is attached or after the Fragment is destroyed).");
   return Glide.get(context).getRequestManagerRetriever();
 }

Glide 是如何做到鏈?zhǔn)降膬?yōu)雅調(diào)用?(精髓之二)

鏈?zhǔn)秸{(diào)用其實(shí)只不過是一種語(yǔ)法招數(shù)。它能讓你通過重用一個(gè)初始操作來(lái)達(dá)到用少量代碼表達(dá)復(fù)雜操作的目的。其實(shí)就是類似builder一樣,把this return 出去,一直可以調(diào)用自己的方法。所以也稱之為方法鏈。

 // Some time in the future:
Glide.with(fragment)
.load(newUrl)
.into(target);

鏈?zhǔn)秸{(diào)用的好與不好:

  1. 編程性強(qiáng)
  2. 可讀性強(qiáng)
  3. 代碼簡(jiǎn)潔
  4. 對(duì)程序員的業(yè)務(wù)能力要求高
  5. 不太利于代碼調(diào)試

Glide 坑爹的 wrap_content 不支持的問題

官方說了的,不支持并且不建議imageview設(shè)置wrap_content。因?yàn)檫@樣 glide 不知道要加載多大的圖片給我們才好,在他的接口(Sizes and dimensions)中也有體現(xiàn)。普通的imageview其實(shí)也還好,如果放在列表(RecyclerView)中, 由于我們并不知道目標(biāo)圖片大小是多大的,所以我們選擇了wrap_content,那么在上下來(lái)回滾動(dòng)過程中,就會(huì)導(dǎo)致圖片一會(huì)大一會(huì)小的bug.

官方 issue 作者回答如下:

 Don't use wrap_content.

Even if you don't use Glide, wrap_content necessarily means that the size of your views in RecyclerView are going to change from item to item. That's going to cause all sorts of UI weirdness.

One option is to try to obtain the image dimensions in whatever metadata you're using to populate the RecyclerView. Then you can set a fixed View size in onBindViewHolder so the view size at least doesn't change when the image is loaded. You're still likely to see weird scroll bar behavior though.

If nothing else, you can always pick a uniform size that's large enough for all items and use the same consistent size for every item.
For the image file size, you can downscale or upscale by setting the ImageView size manually to 150dp x 150dp. Ultimately either you need uniform view sizes or predetermined view sizes. There's nothing else that will prevent content from expanding or shrinking in your RecyclerView.

For the placeholder bit, I think that will be fixed by 648c58e, you can check by trying the 4.2.0-SNAPSHOT version: http://bumptech.github.io/glide/dev/snapshots.html.

so...還是建議我們指定圖片的大小。

Glide 坑爹的 support包 版本問題

為什么會(huì)有這個(gè)問題呢?其實(shí)剛才已經(jīng)提到了的 ,由于它用到了 fragmen t,那么自然就有版本沖突問題。support 包大家都懂的,不同的版本,差異可能巨大,有個(gè)段子就是說 Google 的 support 包 大概是招了個(gè)實(shí)習(xí)生寫的。不同的版本沖突可能會(huì)編譯不過,可能會(huì)有 ‘nosuchmethod’ 等等問題。
比如我們產(chǎn)線現(xiàn)在的用的是 Glide 版本是 4.3.1,之所以遲遲沒有升級(jí)到最新版本,就是因?yàn)楹竺娴陌姹?Glide采用了 27編譯。。而我們項(xiàng)目才25 。。。 中間這個(gè)編譯升級(jí)的風(fēng)險(xiǎn)。有點(diǎn)不可控。所以一直沒有升級(jí)上去。
所以建議,在升級(jí) Glide 版本的時(shí)候 看一下對(duì)應(yīng)版本源碼中依賴的 support 版本是多少。

寫在最后

之所以今天簡(jiǎn)單的跟大家聊一聊 Glide。其實(shí)也只是找了一個(gè)項(xiàng)目中用到的開源庫(kù)作為例子,想跟大家聊聊,當(dāng)項(xiàng)目中需要技術(shù)選型的時(shí)候,不能給的答案是:因?yàn)榇蠹叶荚谟冒。?/p>

而我更想知道的是,大家為什么會(huì)選擇它,不僅僅是人群中多看了你一眼, 而是從外表 API的“美”,再到內(nèi)在框架設(shè)計(jì)的 “美”。只有知其所以然,那么當(dāng)遇到坑的時(shí)候,才知道如何去解決它。而不是簡(jiǎn)單的“跟風(fēng)似的” “一見鐘情”。。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評(píng)論 6 538
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,067評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,467評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,468評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,184評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,582評(píng)論 1 325
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,794評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,343評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,096評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,291評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,513評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,941評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,190評(píng)論 1 291
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,026評(píng)論 3 396
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,253評(píng)論 2 375

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

  • 7.1 壓縮圖片 一、基礎(chǔ)知識(shí) 1、圖片的格式 jpg:最常見的圖片格式。色彩還原度比較好,可以支持適當(dāng)壓縮后保持...
    AndroidMaster閱讀 2,537評(píng)論 0 13
  • 學(xué)習(xí)來(lái)源:郭霖大師博客地址 1、圖片加載框架挺多,如Volley、Glide、Picasso、Fresco、本次是...
    子謙寶寶閱讀 1,761評(píng)論 0 6
  • 作者簡(jiǎn)介 原創(chuàng)微信公眾號(hào)郭霖 WeChat ID: guolin_blog 現(xiàn)在Android上的圖片加載框架非常...
    木木00閱讀 4,298評(píng)論 1 17
  • 最近在做群聊功能,使用了環(huán)信的SDK,在環(huán)信demo中無(wú)意之中看到了glide框架,簡(jiǎn)單了解后,發(fā)現(xiàn)這個(gè)框架很強(qiáng)(...
    guggle閱讀 2,171評(píng)論 1 7
  • 一、簡(jiǎn)介 在泰國(guó)舉行的谷歌開發(fā)者論壇上,谷歌為我們介紹了一個(gè)名叫Glide的圖片加載庫(kù),作者是bumptech。這...
    天天大保建閱讀 7,525評(píng)論 2 28