什麼是Glide?
Glide是一個加載圖片的庫,作者是bumptech,它是在泰國舉行的google 開發者論壇上google爲我們介紹的,這個庫被廣泛的運用在google的開源項目中。
Glide解決什麼問題?
Glide是一個非常成熟的圖片加載庫,他可以從多個源加載圖片,如:網路,本地,Uri等,更重要的是他內部封裝了非常好的緩存機制並且在處理圖片的時候能保持一個低的內存消耗。
Glide怎麼使用?
在Glide的使用方面,它和Picasso的使用方法是比較相似的,並且他們的運行機制也有很多相似的地方,很多博文會把兩者進行比較,此文也採用同樣的方式,通過比較兩者來學習他們之間的優點和不足。
首先,當我們使用這兩個庫的時候第一步要做的就是導入庫,Picasso好說,直接依賴就行,但是Glide要注意,這個庫是要依賴於support liberary v4的,所以用這個庫的時候,不要忘了依賴v4包。
基本使用
在基本使用方面這兩個庫非常的相似,如下代碼所示:
Picasso:
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Picasso.with(context) .load(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://inthecheesefactory.com/uploads/source/glidepicasso/cover.jpg"</span>) .into(ivImg);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
Glide:
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Glide.with(context) .load(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://inthecheesefactory.com/uploads/source/glidepicasso/cover.jpg"</span>) .into(ivImg);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
看到沒有,表面上看是不是非常相似,其實他們有一個不一樣的地方,就是Picasso的with只能傳入context,而Glide的with可以傳入context,還可以是Activity或者是Fragment,你可能會問,這有什麼用呢?用處就是圖片的加載可以和Activity或者Fragment保持一致,不至於出現,Activity已經暫停了,但是圖片卻還在加載的情況。
默認的Bitmap格式是RGB_565
一下是Picasso和Glide加載後的結果(1920x1080 像素的圖片被加載到768x432像素的imageview中):
你可以看到,被Glide加載的圖片在質量上不如Picasso加載的圖片,這是爲什麼?其實是因爲Glide的Bitmap默認的格式是RGB_565,而Picasso用的是ARGB_8888,所以雖然質量上不如Picasso(其實在手機上也不明顯),但是RGB_565格式的圖片僅僅消耗ARGB_8888格式圖片一半的內存。
Here is the memory consumption graphs between Picasso at ARGB8888 and Glide at RGB565. (Base application consumes around 8MB)
下圖是Picass的ARGB8888格式圖片和Glide的RGB565格式圖片的內存消耗比較(應用本身大約佔8M):
如果你對圖片沒有過高的要求,那麼用默認的格式就可以,但是如果你對圖片質量要求較高,那麼可以把圖片的格式轉換爲ARGB8888,方法就是通過繼承GlideMoudle,如下所示:
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">GlideConfiguration</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">GlideModule</span> {</span> <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">applyOptions</span>(Context context, GlideBuilder builder) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Apply options to the builder here.</span> builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); } <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">registerComponents</span>(Context context, Glide glide) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// register ModelLoaders here.</span> } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>
然後在AndroidManifest.xml中進行定義:
<code class="language-xml hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">meta-data</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"com.inthecheesefactory.lab.glidepicasso.GlideConfiguration"</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:value</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"GlideModule"</span>/></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
在次看下圖,是不是完全一樣了呢?
那讓我們再看一看兩者之間的內存消耗:
我們發現,雖然用的圖片格式是一樣的,並且Glide加載的幾乎是先前的兩倍內存,但是Picasso消耗的內存仍然遠大於Glide.
這是因爲,Picasso加載了完整尺寸的圖片(1920x1080像素)進入內存,當繪圖的時候,讓GPU即時的恢復到所需要的尺寸(768x432像素),然而Glide則加載精確的imageview尺寸進入內存,當然,我們可以手動使Picasso也使用這種方式加載圖片:
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Picasso.with(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>) .load(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://nuuneoi.com/uploads/source/playstore/cover.jpg"</span>) .resize(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">768</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">432</span>) .into(ivImgPicasso);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
上面的方式有侷限性,就是我們必須知道imageview的精確尺寸,而如果我們的imageview設置了wrap,我們就不能用上面的那種方式了,而需要改爲下面的方式:
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Picasso.with(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>) .load(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://nuuneoi.com/uploads/source/playstore/cover.jpg"</span>) .fit() .centerCrop() .into(ivImgPicasso);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
現在,我們再來看內存消耗圖:
哈哈,兩者的內存消耗現在差不多一樣了,但是不得不說的是在這一點上Glide確實比Picasso做的要好,因爲Glide可以在每種情況下自動的計算Imageview的尺寸。
圖片的質量細節
當我把imageview的尺寸調整到和圖片一樣大的時候(1920x1080像素),我們來觀察一下下面的圖片:
這次兩張圖片的對比就比較明顯了,Glide加載的圖片可以明顯的看到鋸齒像素點,但是當用戶使用應用的時候,這並不是那麼容易察覺,並且,如果真的忍受不了這種小瑕疵,可以把圖片格式調整到ARGB_8888。
外部緩存
在默認情況下Picasso和Glide的外部緩存機制是非常不一樣的,通過實驗可以發現(1920x1080 像素的圖片被加載到768x432像素的imageview中),Glide緩存的是768x432像素的圖片,而Picasso緩存的是整張圖片(1920x1080像素)。
如果加載的圖片是RGB565模式,緩存圖片也是RGB565模式。
當我們調整imageview的大小時,Picasso會不管imageview大小是什麼,總是直接緩存整張圖片,而Glide就不一樣了,它會爲每個不同尺寸的Imageview緩存一張圖片,也就是說不管你的這張圖片有沒有加載過,只要imageview的尺寸不一樣,那麼Glide就會重新加載一次,這時候,它會在加載的imageview之前從網絡上重新下載,然後再緩存。
防止各位不明白,再來舉個例子,如果一個頁面的imageview是200*200像素,而另一個頁面中的imageview是100*100像素,這時候想要讓兩個imageview像是同一張圖片,那麼Glide需要下載兩次圖片,並且緩存兩張圖片。
但是我們可以通過如下的方法來讓Glide即緩存全尺寸的圖片,有緩存不同尺寸的圖片:
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Glide.with(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>) .load(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://nuuneoi.com/uploads/source/playstore/cover.jpg"</span>) .diskCacheStrategy(DiskCacheStrategy.ALL) .into(ivImgGlide);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
Glide的這種默認的緩存機制有一個優點,就是它可以加快圖片加載的速度(可以理解爲以空間換時間),而Picasso會造成一定的延遲,因爲它在加載到imageview的時候,總是需要調整大小,確實Picasso有一個立即顯示圖片的方法(如下所示),但是這還是消除不了延時。
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Picasso</span> .noFade();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
在外部緩存方面Glide和Pcasso各有所長,你可以選擇合適自己的來用(也就是對於你的app來說是控件重要還是時間重要)。
特性
你幾乎可以用Glide來做Pcasso可以做的所有事情,並且他們的代碼風格也非常類似:
調整圖片尺寸:
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Picasso</span> .resize(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Glide</span> .override(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
Center Cropping:
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Picasso</span> .centerCrop(); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Glide</span> .centerCrop();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
圖形變換(Transforming):
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Picasso</span> .transform(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> CircleTransform()) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Glide</span> .transform(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> CircleTransform(context))</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
設置佔位圖片和錯誤圖片:
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Picasso</span> .placeholder(R.drawable.placeholder) .error(R.drawable.imagenotfound) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Glide</span> .placeholder(R.drawable.placeholder) .error(R.drawable.imagenotfound)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>
有什麼Glide可以做Pcasso卻做不了
Glide的一個明顯的優點就是它可以加載gif圖片,你可能說我用Picasso加載也不報錯啊?你要注意,用Picasso加載的gif圖片是不會動的,如下所示:
因爲Glide被設計成能和Activity/Fragment的生命週期完美的相結合,因此gif動畫將隨着Activity/Fragment的生命週期自動的開始和停止。
gif的緩存和一般的圖片也是一樣的,也是第一次加載的時候調整大小,然後緩存。
但是,要注意的是,通過測量,我們可以發現gif圖片將消耗非常多的內存,因此使用它的時候要慎重。
除了加載gif圖片外,Glide還可以解析任何的video文件成爲一個靜態圖片。
另一個比較有用的特性是,你可以配置顯示圖片的動畫,而Picasso只支持一個淡入(fading in)動畫效果。
你也可以用thumbnail()
來創造一個image的thumbnail(極小)的圖片。
還有很多的特性,但是一般都不太常用,如,把一個圖片的編碼轉換爲字節數組,等。
配置
我們可以對很多的配置做出調整,如,外部緩存的大小和位置,內部緩存的最大限制,Bitmap的格式等等,至於更多的配置,可以參考配置頁面。
庫的大小
Picasso的大小大約是118KB,而Glide大約有430KB。
一個庫的大小有什麼意義嗎?確實,我也認爲意義不大!
我們再來看一下兩者之間的方法數量的比較:
值得注意的是,在Android DEX file中的方法是有限制的,最大方法數爲65535個,從這一點來說,Glide的方法確實不少,並且,混淆器也建議對我們的項目進行混淆。
總結
Glide和Picasso都不是完美的,從某些方面來說,Glide在圖片的緩存上來說是比較不錯的,因爲它的速度比較快,另外,它也可以有效的防止OOM錯誤,而加載gif圖片也是Glide的一大優勢,但是默認情況下picasso的圖片質量是很高的。
另外的一點小建議是,使用Glide的時候把圖片的格式改爲ARGB8888並且緩存全尺寸和其他尺寸的圖片,這樣使用可以讓加載圖片更好。
資源
以下是一些關於Glide的資源:
- Glide 3.0: a media management library for Android
- Glide Wiki
- Android Picasso vs Glide
- Android: Image loading libraries Picasso vs Glide
參考原文:Introduction to Glide, Image Loader Library for Android, recommended by Google