本文的內容大部分都是參考了下面這個連接中Glide
分類的文章:android
爲了區分,咱們這篇只介紹一些基本用法,掌握這些基本就能夠在項目中使用Glide
了,而關於如何自定義Target/Glide Module
等高級的用法,以後再進行討論。github
在使用前,首先須要在build.gradle
中引入:緩存
dependencies {
//....
compile 'com.github.bumptech.glide:glide:3.7.0'
//...
}
複製代碼
下面是Glide
加載一張網絡靜態圖片最基本的用法:bash
Glide
.with(this) //傳入關聯的Context,若是是Activity/Fragment,那麼它會根據組件當前的狀態來控制請求。
.load("http://i.imgur.com/DvpvklR.png") //須要加載的圖片,大多數狀況下就是網絡圖片的連接。
.into(getImageView()); //用來展示圖片的ImageView.
複製代碼
load
的其它用法在第二章的例子當中,當咱們調用完.with(Context context)
以後,會返回一個RequestManager
對象,以前咱們就是調用它的load(String string)
方法,除此以外,還提供了下面的這些load
方法,load
方法最終會返回一個DrawableTypeRequest<xxxx>
,而xxx
就是咱們傳入的參數的類型: 服務器
load(byte[] model)
,從byte[]
中讀取load(File file)
,從File
中讀取load(Integer resourceId)
,從resourceId
中讀取load(String string)
,從String
當中讀取,這個通常對應於網絡圖片的連接,這個圖片有多是普通的圖片,也多是一個Gif
,當咱們須要展現一個Gif
圖片時,只須要像加載普通圖片同樣就能夠了,在加載完以後,這個Gif
會被自動播放。load(T model)
,從任意類型T
的中讀取,這個後面講到自定義Model
時再介紹load(Uri uri)
,從Uri
類型中讀取,這個Uri
必須可以被UriLoader
識別。loadFromMediaStore(Uri uri)
,從媒體設備的Uri
中讀取,這個方法用來展現一個本地媒體視頻的縮略圖,也就是視頻的第一幀,須要注意,這個連接只能是本地的,網絡上視頻連接地址是無效的。下面是各個方法加載的例子:網絡
//從byte[]中加載.
public void loadByteArray(View view) {
Bitmap sourceBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.book_local);
ByteArrayOutputStream bArrayOS = new ByteArrayOutputStream();
sourceBitmap.compress(Bitmap.CompressFormat.PNG, 100, bArrayOS);
sourceBitmap.recycle();
byte[] byteArray = bArrayOS.toByteArray();
try {
bArrayOS.close();
} catch (Exception e) {
e.printStackTrace();
}
Glide.with(this)
.load(byteArray)
.into(mImageView);
}
//從File中加載.
public void loadFile(View view) {
String storePath = "mnt/sdcard/book_local.jpg";
File file = new File(storePath);
Glide.with(this)
.load(file)
.into(mImageView);
}
//從resourceId中加載.
public void loadResourceId(View view) {
Glide.with(this)
.load(R.drawable.book_local)
.into(mImageView);
}
//從普通url中加載.
public void loadNormalUrl(View view) {
Glide.with(this)
.load("http://i.imgur.com/DvpvklR.png")
.into(mImageView);
}
//從gif加載.
public void loadGif(View view) {
Glide.with(this)
.load("http://s1.dwstatic.com/group1/M00/66/4D/d52ff9b0727dfd0133a52de627e39d2a.gif")
.diskCacheStrategy(DiskCacheStrategy.SOURCE) //要加上這句,不然有可能會出現加載很慢,或者加載不出來的狀況.
.into(mImageView);
}
//從本地媒體視頻中加載.
public void loadMedia(View view) {
String storePath = "mnt/sdcard/media.mp4";
File file = new File(storePath);
Glide.with(this)
.load(Uri.fromFile(file))
.into(mImageView);
}
複製代碼
有時候因爲網絡緣由,致使請求耗時,此時就須要在獲得圖片資源以前,採用一個佔位圖片,這樣就不會顯得界面太空,placeHolder
就是作這個事的,當咱們調用了into
方法以後,若是須要從網絡上獲取圖片,那麼它會先展現placeHolder
設置的圖片,placeHolder
除了支持傳入resourceId
,還支持直接傳入一個Drawable
對象。框架
@Override
public DrawableRequestBuilder<ModelType> placeholder(int resourceId) {
super.placeholder(resourceId);
return this;
}
@Override
public DrawableRequestBuilder<ModelType> placeholder(Drawable drawable) {
super.placeholder(drawable);
return this;
}
複製代碼
使用placeHolder
的例子:ide
public void loadHolder(View view) {
Glide.with(this)
.load("http://i.imgur.com/DvpvklR.png")
.placeholder(R.drawable.book_placeholder)
.into(mImageView);
}
複製代碼
有時候,當咱們請求網絡圖片失敗時,咱們但願給用戶一些提示,這時候給它設置一些回調,並在回調當中進行處理。可是通常狀況下,咱們顯示一個表示錯誤的本地圖片就能夠了,爲了和前面加載時的佔位圖片區分,它提供了另外一個error()
方法,和placeHolder
相似,咱們能夠給它傳入一個resourceId
或者Drawable
對象。gradle
public void loadHolderError(View view) {
Glide.with(this)
.load("http://i.imgur.com/DvpvklR.png")
.asGif() //爲了模擬加載失敗的狀況.
.placeholder(R.drawable.book_placeholder)
.error(R.drawable.book_error)
.into(mImageView);
}
複製代碼
上面爲了模擬失敗的狀況,咱們傳入了一個png
的連接,可是指定爲加載asGif()
資源。 咱們發現它會先展現placeHolder
的資源,再展現error
的資源。
不管是placeHolder
仍是error
,都會涉及到切換ImageView
的圖片,這時咱們能夠經過設置一個動畫來讓這個切換的過程顯得不那麼突兀,默認狀況下動畫是開啓的,crossFade
有下面這三個重載方法:
crossFade()
:採用默認動畫和默認時長。crossFade(int duration)
:採用默認動畫,自定義時長。crossFade(int animationId, int duration)
:採用自定義動畫,並自定義時長。public void loadCustomCrossFade(View view) {
Glide.with(this)
.load("http://i.imgur.com/DvpvklR.png")
.placeholder(R.drawable.book_placeholder)
.crossFade(5000) //改變的時長.
.into(mImageView);
}
複製代碼
固然咱們也能夠經過dontAnimate
,來關閉動畫,這樣在切換的時候就不會出現動畫。
public void loadNoCrossFade(View view) {
Glide.with(this)
.load("http://i.imgur.com/DvpvklR.png")
.placeholder(R.drawable.book_placeholder)
.dontAnimate()
.into(mImageView);
}
複製代碼
和Picasso
相比,Glide
提供了一種更加高效的處理方式,它會把內存和緩存中的圖片限制到所展現的ImageView
的返回內,Picasso
也能夠實現這一功能,可是須要調用fit()
方法。在使用Glide
時,若是咱們不但願它自動地去匹配ImageView
的寬高,那麼能夠調用override(width, height)
,這樣圖片資源在被展現以前就會裁剪爲指定的大小。
這個方法還有另外一種場景,就是當咱們確切的知道須要加載多大的圖片,可是此時ImageView
的寬高並無獲得。
由於有時候採用override
直接裁剪圖片有可能致使只裁剪到了沒必要要的信息,所以Glide
還提供了兩個相似於ImageView
中的scaleType
屬性:
centerCrop
:使原始的圖片的寬高按同等比例放大到override
所指定的大小,並裁剪到多餘的部分,這時最終的圖片資源的大小爲(width, height)
fitCenter
:使得原始圖片的寬高放大到小於等於override
所指定的寬高,所以,咱們最終獲得圖片的大小有可能不爲(width, height)
,也就是說不會撐滿整個ImageView
。 下面是相關的代碼:public void loadOverride(View view) {
Glide.with(this)
.load(R.drawable.shader_pic)
.override(20, 20)
.into(mImageView);
}
public void loadOverrideCenterCrop(View view) {
Glide.with(this)
.load(R.drawable.shader_pic)
.override(20, 20)
.centerCrop()
.into(mImageView);
}
public void loadOverrideFitCenter(View view) {
Glide.with(this)
.load(R.drawable.shader_pic)
.override(20, 20)
.fitCenter()
.into(mImageView);
}
複製代碼
ImageView
的scaleType
的關係因爲ImageView
的展現還須要受android:scaleType
的影響,這裏狀況有不少,因此上面裁剪出來,並非說在ImageView
裏面展現就是20 * 20
,具體會出現的狀況不少,這個以後再專門分析。
Gif
圖片在第二節中,咱們簡單的介紹瞭如何用Glide
展現Gif
圖片的展現,下面咱們深刻地討論一下其它兩點。
asGif()
有時候,咱們獲取的Gif
圖片連接是服務器配置的,所以咱們沒法知道這個連接究竟是不是一個Gif
圖片。這時咱們能夠配置一個asGif()
選項,這樣Glide
就會知道咱們是須要加載一個Gif
圖片,當這個連接不是Gif
時,加載就會失敗,若是咱們定義了.error(xxx)
,就會展現這個失敗的圖片。 例如,下面這段代碼就會失敗:
public void loadHolderError(View view) {
Glide.with(this)
.load("http://i.imgur.com/DvpvklR.png") //傳入的是一個靜態圖片的連接.
.asGif() //爲了模擬加載失敗的狀況.
.placeholder(R.drawable.book_placeholder)
.error(R.drawable.book_error)
.into(mImageView);
}
複製代碼
asBitmap()
如今討論另一種狀況,在列表當中,雖然咱們得到的是Gif
連接,可是咱們但願這時候不讓它播放,這時候就能夠指定asBitmap()
,那麼就只會展現Gif
圖片的第一幀。
若是咱們使用了.diskCacheStrategy(DiskCacheStrategy.SOURCE)
,那麼Gif
資源的加載將會更快。
對於任何一個網絡圖片加載框架來講,緩存無疑是最關鍵的部分,Glide
使用了內存和磁盤緩存來避免沒必要要的網絡請求,同時它也提供了一系列地接口讓使用者自定義緩存策略。
默認狀況下,Glide
會將圖片資源緩存到內存當中。而若是使用了skipMemoryCache(true)
,Glide
不會將這張圖片緩存到內存當中。 有一點須要注意:若是以前對某個指向url
的圖片使用了內存緩存,後面又用skipMemoryCache(true)
聲明想讓同一個url
不緩存到內存中,那麼是不會生效的。
當某個圖片變化很快時,咱們有可能不須要將它緩存到磁盤當中,咱們能夠採用diskCacheStrategy(int mode)
來定義緩存的策略,Glide
默認狀況下既會緩存原始的圖片,也會緩存解析後的圖片,舉個例子,假如服務器上的圖片是1000 * 1000
,而ImageView
的大小隻有500 * 500
,默認狀況下Glide
會緩存這兩個版本的圖片,咱們能夠設定的磁盤緩存類型有下面四種:
DiskCacheStrategy.NONE
:不緩存DiskCacheStrategy.SOURCE
:只緩存原始大小的圖片,也就是1000 * 1000
。DiskCacheStrategy.RESULT
:只緩存解析以後的圖片,也就是上面500 * 500
的圖片,也就是說假如咱們有兩個不一樣大小的ImageView
,用他們加載同一個url
的圖片,那麼最終磁盤當中會有兩份不一樣大小的圖片資源。DiskCacheStrategy.ALL
:緩存全部版本的圖片。如今咱們介紹一下采用了DiskCacheStrategy.RESULT
後的緩存文件名的命名策略,具體能夠參考下面這篇文章:
https://github.com/bumptech/glide/wiki/Caching-and-Cache-Invalidation
緩存文件的命名會依賴於四個部分:
DataFecher
的getId()
方法的返回值,通常狀況下就是Data Model
的toString
方法。對於傳入String
類型的網絡連接而言,就是url
,而若是是File
,那麼就是File
的path
。override(width, height)
,那就是指定的數值,默認狀況下是Target
的getSize()
方法,也就是ImageView
的寬高。encoders
和decoders
的toString
方法。url
沒有變,可是服務器上這個url
對應的圖片資源更新了,咱們就能夠經過.signature(xxx)
來刷新緩存。上面咱們討論了兩種緩存策略的定義,這兩種策略是相互獨立的,默認狀況下內存的緩存爲打開,而磁盤的緩存策略爲DiskCacheStrategy.ALL
。
有時候,在同一個界面上咱們會展現多個圖片,而爲了用戶體驗,那麼某個圖片咱們但願先加載出來,這時候就能夠採用.priority(int priority)
來定義請求的優先級,固然,這些優先級只是給Glide
做爲參考,由於還涉及到圖片的大小,服務器的響應事件和網絡環境等因素,最後圖片展現的順序並不必定是根據優先級來的,可選的優先級包括:
Priority.LOW
Priority.NORMAL
Priority.HIGH
Priority.IMMEDIATE
前面,咱們介紹了placeHolder
,它能夠指定一個本地資源,用來在網絡資源加載完成以前進行展現,而thumbnails
則能夠認爲是一個動態的placeHolder
,與placeHolder
不一樣,咱們能夠給它指定一個網絡圖片連接。若是這個縮略圖請求在load
請求以前返回那麼,那麼會先展現這個圖片,等到load
請求返回以後,這個圖片就會消失。假如縮略圖的請求在load
請求以後返回,那麼請求結果會被丟棄掉。 Glide
提供了兩種指定縮略圖的方式:
Simple Thumbnails
public void loadScaleThumbnail(View view) {
Glide.with(this)
.load("http://i.imgur.com/DvpvklR.png")
.diskCacheStrategy(DiskCacheStrategy.NONE)
.thumbnail(0.1f)
.into(mImageView);
}
複製代碼
Complete Different Request
thumbnails
還支持傳入一個Glide Request
做爲參數,這個請求和本來的請求是相互獨立的,咱們能夠給它指定一個徹底不一樣的url
、緩存策略、大小等等。
public void loadRequestThumbnail(View view) {
DrawableRequestBuilder<String> thumbnailRequest = Glide
.with(this)
.load("http://i.imgur.com/DvpvklR.png");
Glide.with(this)
.load("http://s1.dwstatic.com/group1/M00/66/4D/d52ff9b0727dfd0133a52de627e39d2a.gif")
.diskCacheStrategy(DiskCacheStrategy.NONE)
.thumbnail(thumbnailRequest)
.into(mImageView);
}
複製代碼