一咬展、概述
本文的內(nèi)容大部分都是參考了下面這個鏈接中Glide
分類的文章:
為了區(qū)分俏站,我們這篇只介紹一些基本用法土思,掌握這些基本就可以在項目中使用Glide
了,而關(guān)于如何自定義Target/Glide Module
等高級的用法屋灌,之后再進行討論。
二、導(dǎo)入依賴包&加載網(wǎng)絡(luò)靜態(tài)圖片
在使用前煤搜,首先需要在build.gradle
中引入:
dependencies {
//....
compile 'com.github.bumptech.glide:glide:3.7.0'
//...
}
下面是Glide
加載一張網(wǎng)絡(luò)靜態(tài)圖片最基本的用法:
Glide
.with(this) //傳入關(guān)聯(lián)的Context,如果是Activity/Fragment唧席,那么它會根據(jù)組件當前的狀態(tài)來控制請求擦盾。
.load("http://i.imgur.com/DvpvklR.png") //需要加載的圖片嘲驾,大多數(shù)情況下就是網(wǎng)絡(luò)圖片的鏈接。
.into(getImageView()); //用來展現(xiàn)圖片的ImageView.
三迹卢、load
的其它用法
在第二章的例子當中辽故,當我們調(diào)用完.with(Context context)
之后,會返回一個RequestManager
對象腐碱,之前我們就是調(diào)用它的load(String string)
方法誊垢,除此之外,還提供了下面的這些load
方法症见,load
方法最終會返回一個DrawableTypeRequest<xxxx>
喂走,而xxx
就是我們傳入的參數(shù)的類型:
-
load(byte[] model)
,從byte[]
中讀取 -
load(File file)
筒饰,從File
中讀取 -
load(Integer resourceId)
缴啡,從resourceId
中讀取 -
load(String string)
,從String
當中讀取瓷们,這個一般對應(yīng)于網(wǎng)絡(luò)圖片的鏈接业栅,這個圖片有可能是普通的圖片,也可能是一個Gif
谬晕,當我們需要展示一個Gif
圖片時碘裕,只需要像加載普通圖片一樣就可以了,在加載完之后攒钳,這個Gif
會被自動播放帮孔。 -
load(T model)
,從任意類型T
的中讀取不撑,這個后面講到自定義Model
時再介紹 -
load(Uri uri)
文兢,從Uri
類型中讀取,這個Uri
必須能夠被UriLoader
識別焕檬。 -
loadFromMediaStore(Uri uri)
姆坚,從媒體設(shè)備的Uri
中讀取,這個方法用來展示一個本地媒體視頻的縮略圖实愚,也就是視頻的第一幀兼呵,需要注意,這個鏈接只能是本地的腊敲,網(wǎng)絡(luò)上視頻鏈接地址是無效的击喂。
下面是各個方法加載的例子:
//從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) //要加上這句,否則有可能會出現(xiàn)加載很慢碰辅,或者加載不出來的情況.
.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);
}
四懂昂、占位圖片和錯誤圖片
4.1 顯示占位圖片
有時候由于網(wǎng)絡(luò)原因,導(dǎo)致請求耗時没宾,此時就需要在得到圖片資源之前凌彬,采用一個占位圖片潮尝,這樣就不會顯得界面太空,placeHolder
就是做這個事的饿序,當我們調(diào)用了into
方法之后,如果需要從網(wǎng)絡(luò)上獲取圖片羹蚣,那么它會先展示placeHolder
設(shè)置的圖片原探,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
的例子:
public void loadHolder(View view) {
Glide.with(this)
.load("http://i.imgur.com/DvpvklR.png")
.placeholder(R.drawable.book_placeholder)
.into(mImageView);
}
4.2 顯示錯誤圖片
有時候咽弦,當我們請求網(wǎng)絡(luò)圖片失敗時,我們希望給用戶一些提示胁出,這時候給它設(shè)置一些回調(diào)型型,并在回調(diào)當中進行處理。但是一般情況下全蝶,我們顯示一個表示錯誤的本地圖片就可以了闹蒜,為了和前面加載時的占位圖片區(qū)分,它提供了另一個error()
方法抑淫,和placeHolder
類似绷落,我們可以給它傳入一個resourceId
或者Drawable
對象。
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()
資源。
我們發(fā)現(xiàn)它會先展示placeHolder
的資源催式,再展示error
的資源函喉。
4.3 定義圖片切換動畫
無論是placeHolder
還是error
,都會涉及到切換ImageView
的圖片荣月,這時我們可以通過設(shè)置一個動畫來讓這個切換的過程顯得不那么突兀管呵,默認情況下動畫是開啟的,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);
}
4.4 關(guān)閉切換動畫
當然我們也可以通過dontAnimate
,來關(guān)閉動畫咽白,這樣在切換的時候就不會出現(xiàn)動畫啤握。
public void loadNoCrossFade(View view) {
Glide.with(this)
.load("http://i.imgur.com/DvpvklR.png")
.placeholder(R.drawable.book_placeholder)
.dontAnimate()
.into(mImageView);
}
五、獲得圖片資源后晶框,進行裁剪
5.1 裁剪
和Picasso
相比排抬,Glide
提供了一種更加高效的處理方式懂从,它會把內(nèi)存和緩存中的圖片限制到所展示的ImageView
的返回內(nèi),Picasso
也可以實現(xiàn)這一功能蹲蒲,但是需要調(diào)用fit()
方法番甩。在使用Glide
時,如果我們不希望它自動地去匹配ImageView
的寬高届搁,那么可以調(diào)用override(width, height)
缘薛,這樣圖片資源在被展示之前就會裁剪為指定的大小。
這個方法還有另一種場景卡睦,就是當我們確切的知道需要加載多大的圖片宴胧,但是此時ImageView
的寬高并沒有得到。
5.2 定義裁剪的方式
因為有時候采用override
直接裁剪圖片有可能導(dǎo)致只裁剪到了不必要的信息表锻,因此Glide
還提供了兩個類似于ImageView
中的scaleType
屬性:
-
centerCrop
:使原始的圖片的寬高按同等比例放大到override
所指定的大小恕齐,并裁剪到多余的部分,這時最終的圖片資源的大小為(width, height)
-
fitCenter
:使得原始圖片的寬高放大到小于等于override
所指定的寬高瞬逊,因此显歧,我們最終得到圖片的大小有可能不為(width, height)
,也就是說不會撐滿整個ImageView
确镊。
下面是相關(guān)的代碼:
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);
}
5.3 和ImageView
的scaleType
的關(guān)系
由于ImageView
的展示還需要受android:scaleType
的影響追迟,這里情況有很多,所以上面裁剪出來骚腥,并不是說在ImageView
里面展示就是20 * 20
敦间,具體會出現(xiàn)的情況很多,這個之后再專門分析束铭。
六廓块、Gif
圖片
在第二節(jié)中,我們簡單的介紹了如何用Glide
展示Gif
圖片的展示契沫,下面我們深入地討論一下其它兩點带猴。
5.1 asGif()
有時候,我們獲取的Gif
圖片鏈接是服務(wù)器配置的懈万,因此我們無法知道這個鏈接到底是不是一個Gif
圖片拴清。這時我們可以配置一個asGif()
選項,這樣Glide
就會知道我們是需要加載一個Gif
圖片会通,當這個鏈接不是Gif
時口予,加載就會失敗,如果我們定義了.error(xxx)
涕侈,就會展示這個失敗的圖片沪停。
例如,下面這段代碼就會失敗:
public void loadHolderError(View view) {
Glide.with(this)
.load("http://i.imgur.com/DvpvklR.png") //傳入的是一個靜態(tài)圖片的鏈接.
.asGif() //為了模擬加載失敗的情況.
.placeholder(R.drawable.book_placeholder)
.error(R.drawable.book_error)
.into(mImageView);
}
5.2 asBitmap()
現(xiàn)在討論另外一種情況木张,在列表當中众辨,雖然我們獲得的是Gif
鏈接,但是我們希望這時候不讓它播放舷礼,這時候就可以指定asBitmap()
鹃彻,那么就只會展示Gif
圖片的第一幀。
5.3 定義緩存
如果我們使用了.diskCacheStrategy(DiskCacheStrategy.SOURCE)
妻献,那么Gif
資源的加載將會更快浮声。
六、緩存策略
對于任何一個網(wǎng)絡(luò)圖片加載框架來說旋奢,緩存無疑是最關(guān)鍵的部分,Glide
使用了內(nèi)存和磁盤緩存來避免不必要的網(wǎng)絡(luò)請求然痊,同時它也提供了一系列地接口讓使用者自定義緩存策略至朗。
6.1 內(nèi)存緩存策略
默認情況下,Glide
會將圖片資源緩存到內(nèi)存當中剧浸。而如果使用了skipMemoryCache(true)
锹引,Glide
不會將這張圖片緩存到內(nèi)存當中。
有一點需要注意:如果之前對某個指向url
的圖片使用了內(nèi)存緩存唆香,后面又用skipMemoryCache(true)
聲明想讓同一個url
不緩存到內(nèi)存中嫌变,那么是不會生效的。
6.2 磁盤緩存策略
當某個圖片變化很快時躬它,我們有可能不需要將它緩存到磁盤當中腾啥,我們可以采用diskCacheStrategy(int mode)
來定義緩存的策略,Glide
默認情況下既會緩存原始的圖片冯吓,也會緩存解析后的圖片倘待,舉個例子,假如服務(wù)器上的圖片是1000 * 1000
组贺,而ImageView
的大小只有500 * 500
凸舵,默認情況下Glide
會緩存這兩個版本的圖片,我們可以設(shè)定的磁盤緩存類型有下面四種:
-
DiskCacheStrategy.NONE
:不緩存 -
DiskCacheStrategy.SOURCE
:只緩存原始大小的圖片失尖,也就是1000 * 1000
啊奄。 -
DiskCacheStrategy.RESULT
:只緩存解析之后的圖片,也就是上面500 * 500
的圖片掀潮,也就是說假如我們有兩個不同大小的ImageView
菇夸,用他們加載同一個url
的圖片,那么最終磁盤當中會有兩份不同大小的圖片資源仪吧。 -
DiskCacheStrategy.ALL
:緩存所有版本的圖片峻仇。
現(xiàn)在我們介紹一下采用了DiskCacheStrategy.RESULT
后的緩存文件名的命名策略,具體可以參考下面這篇文章:
https://github.com/bumptech/glide/wiki/Caching-and-Cache-Invalidation
緩存文件的命名會依賴于四個部分:
-
DataFecher
的getId()
方法的返回值邑商,一般情況下就是Data Model
的toString
方法摄咆。對于傳入String
類型的網(wǎng)絡(luò)鏈接而言凡蚜,就是url
,而如果是File
吭从,那么就是File
的path
朝蜘。 - 目標的寬高,如果定義了
override(width, height)
涩金,那就是指定的數(shù)值谱醇,默認情況下是Target
的getSize()
方法,也就是ImageView
的寬高步做。 - 用來加載和緩存圖片的
encoders
和decoders
的toString
方法副渴。 - 在加載時的可選簽名,這個方法在某些特殊的場景下很有用全度,例如加載的
url
沒有變煮剧,但是服務(wù)器上這個url
對應(yīng)的圖片資源更新了,我們就可以通過.signature(xxx)
來刷新緩存将鸵。
6.3 兩種策略的關(guān)系
上面我們討論了兩種緩存策略的定義勉盅,這兩種策略是相互獨立的,默認情況下內(nèi)存的緩存為打開顶掉,而磁盤的緩存策略為DiskCacheStrategy.ALL
草娜。
七、請求優(yōu)先級
有時候痒筒,在同一個界面上我們會展示多個圖片宰闰,而為了用戶體驗,那么某個圖片我們希望先加載出來簿透,這時候就可以采用.priority(int priority)
來定義請求的優(yōu)先級议蟆,當然,這些優(yōu)先級只是給Glide
作為參考萎战,因為還涉及到圖片的大小咐容,服務(wù)器的響應(yīng)事件和網(wǎng)絡(luò)環(huán)境等因素,最后圖片展示的順序并不一定是根據(jù)優(yōu)先級來的蚂维,可選的優(yōu)先級包括:
Priority.LOW
Priority.NORMAL
Priority.HIGH
Priority.IMMEDIATE
八戳粒、縮略圖
前面,我們介紹了placeHolder
虫啥,它可以指定一個本地資源蔚约,用來在網(wǎng)絡(luò)資源加載完成之前進行展示,而thumbnails
則可以認為是一個動態(tài)的placeHolder
涂籽,與placeHolder
不同苹祟,我們可以給它指定一個網(wǎng)絡(luò)圖片鏈接。如果這個縮略圖請求在load
請求之前返回那么,那么會先展示這個圖片树枫,等到load
請求返回之后直焙,這個圖片就會消失。假如縮略圖的請求在load
請求之后返回砂轻,那么請求結(jié)果會被丟棄掉奔誓。
Glide
提供了兩種指定縮略圖的方式:
8.1 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);
}
8.2 Complete Different Request
thumbnails
還支持傳入一個Glide Request
作為參數(shù),這個請求和原本的請求是相互獨立的搔涝,我們可以給它指定一個完全不同的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);
}