開(kāi)始
Glide是一款由Bump Technologies開(kāi)發(fā)的圖片加載框架悄谐,使得我們可以在Android平臺(tái)上以極度簡(jiǎn)單的方式加載和展示圖片挺举。
目前矫钓,Glide最新的穩(wěn)定版本是3.7.0裁替,雖然4.0已經(jīng)推出RC版了橄仆,但是暫時(shí)問(wèn)題還比較多。因此耳奕,我們這個(gè)系列的博客都會(huì)使用Glide 3.7.0版本來(lái)進(jìn)行講解绑青,這個(gè)版本的Glide相當(dāng)成熟和穩(wěn)定。
要想使用Glide屋群,首先需要將這個(gè)庫(kù)引入到我們的項(xiàng)目當(dāng)中闸婴。新建一個(gè)GlideTest項(xiàng)目,然后在app/build.gradle文件當(dāng)中添加如下依賴:
dependencies {
compile 'com.github.bumptech.glide:glide:3.7.0'
}
如果你還在使用Eclipse芍躏,可以點(diǎn)擊 這里 下載Glide的jar包邪乍。
另外,Glide中需要用到網(wǎng)絡(luò)功能,因此你還得在AndroidManifest.xml中聲明一下網(wǎng)絡(luò)權(quán)限才行:
<uses-permission android:name="android.permission.INTERNET" />
就是這么簡(jiǎn)單庇楞,然后我們就可以自由地使用Glide中的任意功能了榜配。
加載圖片
現(xiàn)在我們就來(lái)嘗試一下如何使用Glide來(lái)加載圖片吧。比如這是必應(yīng)上一張首頁(yè)美圖的地址:
http://cn.bing.com/az/hprichbg/rb/Dongdaemun_ZH-CN10736487148_1920x1080.jpg
然后我們想要在程序當(dāng)中去加載這張圖片吕晌。
那么首先打開(kāi)項(xiàng)目的布局文件蛋褥,在布局當(dāng)中加入一個(gè)Button和一個(gè)ImageView,如下所示:
<?xml version="1.0" encoding="utf-8"?>
http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Load Image"
android:onClick="loadImage"
/>
<ImageView
android:id="@+id/image_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
為了讓用戶點(diǎn)擊Button的時(shí)候能夠?qū)偛诺膱D片顯示在ImageView上睛驳,我們需要修改MainActivity中的代碼烙心,如下所示:
public class MainActivity extends AppCompatActivity {
ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.image_view);
}
public void loadImage(View view) {
String url = "http://cn.bing.com/az/hprichbg/rb/Dongdaemun_ZH-CN10736487148_1920x1080.jpg";
Glide.with(this).load(url).into(imageView);
}
}
沒(méi)錯(cuò),就是這么簡(jiǎn)單“匕校現(xiàn)在我們來(lái)運(yùn)行一下程序弃理,效果如下圖所示:
可以看到,一張網(wǎng)絡(luò)上的圖片已經(jīng)被成功下載屎蜓,并且展示到ImageView上了痘昌。
而我們到底做了什么?實(shí)際上核心的代碼就只有這一行而已:
Glide.with(this).load(url).into(imageView);
1
千萬(wàn)不要小看這一行代碼炬转,實(shí)際上僅僅就這一行代碼辆苔,你已經(jīng)可以做非常非常多的事情了,包括加載網(wǎng)絡(luò)上的圖片扼劈、加載手機(jī)本地的圖片驻啤、加載應(yīng)用資源中的圖片等等。
下面我們就來(lái)詳細(xì)解析一下這行代碼荐吵。
首先骑冗,調(diào)用Glide.with()方法用于創(chuàng)建一個(gè)加載圖片的實(shí)例。with()方法可以接收Context先煎、Activity或者Fragment類型的參數(shù)贼涩。也就是說(shuō)我們選擇的范圍非常廣,不管是在Activity還是Fragment中調(diào)用with()方法薯蝎,都可以直接傳this遥倦。那如果調(diào)用的地方既不在Activity中也不在Fragment中呢?也沒(méi)關(guān)系占锯,我們可以獲取當(dāng)前應(yīng)用程序的ApplicationContext袒哥,傳入到with()方法當(dāng)中。注意with()方法中傳入的實(shí)例會(huì)決定Glide加載圖片的生命周期消略,如果傳入的是Activity或者Fragment的實(shí)例堡称,那么當(dāng)這個(gè)Activity或Fragment被銷毀的時(shí)候,圖片加載也會(huì)停止艺演。如果傳入的是ApplicationContext粮呢,那么只有當(dāng)應(yīng)用程序被殺掉的時(shí)候婿失,圖片加載才會(huì)停止。
接下來(lái)看一下load()方法啄寡,這個(gè)方法用于指定待加載的圖片資源。Glide支持加載各種各樣的圖片資源哩照,包括網(wǎng)絡(luò)圖片挺物、本地圖片、應(yīng)用資源飘弧、二進(jìn)制流识藤、Uri對(duì)象等等。因此load()方法也有很多個(gè)方法重載次伶,除了我們剛才使用的加載一個(gè)字符串網(wǎng)址之外痴昧,你還可以這樣使用load()方法:
// 加載本地圖片
File file = new File(getExternalCacheDir() + "/image.jpg");
Glide.with(this).load(file).into(imageView);
// 加載應(yīng)用資源
int resource = R.drawable.image;
Glide.with(this).load(resource).into(imageView);
// 加載二進(jìn)制流
byte[] image = getImageBytes();
Glide.with(this).load(image).into(imageView);
// 加載Uri對(duì)象
Uri imageUri = getImageUri();
Glide.with(this).load(imageUri).into(imageView);
最后看一下into()方法,這個(gè)方法就很簡(jiǎn)單了冠王,我們希望讓圖片顯示在哪個(gè)ImageView上赶撰,把這個(gè)ImageView的實(shí)例傳進(jìn)去就可以了。當(dāng)然柱彻,into()方法不僅僅是只能接收ImageView類型的參數(shù)豪娜,還支持很多更豐富的用法,不過(guò)那個(gè)屬于高級(jí)技巧哟楷,我們會(huì)在后面的文章當(dāng)中學(xué)習(xí)瘤载。
那么回顧一下Glide最基本的使用方式,其實(shí)就是關(guān)鍵的三步走:先with()卖擅,再load()鸣奔,最后into()。熟記這三步惩阶,你就已經(jīng)入門Glide了挎狸。
占位圖
現(xiàn)在我們來(lái)學(xué)一些Glide的擴(kuò)展內(nèi)容。其實(shí)剛才所學(xué)的三步走就是Glide最核心的東西琳猫,而我們后面所要學(xué)習(xí)的所有東西都是在這個(gè)三步走的基礎(chǔ)上不斷進(jìn)行擴(kuò)展而已伟叛。
觀察剛才加載網(wǎng)絡(luò)圖片的效果,你會(huì)發(fā)現(xiàn)脐嫂,點(diǎn)擊了Load Image按鈕之后统刮,要稍微等一會(huì)圖片才會(huì)顯示出來(lái)。這其實(shí)很容易理解账千,因?yàn)閺木W(wǎng)絡(luò)上下載圖片本來(lái)就是需要時(shí)間的侥蒙。那么我們有沒(méi)有辦法再優(yōu)化一下用戶體驗(yàn)?zāi)兀慨?dāng)然可以匀奏,Glide提供了各種各樣非常豐富的API支持鞭衩,其中就包括了占位圖功能。
顧名思義,占位圖就是指在圖片的加載過(guò)程中论衍,我們先顯示一張臨時(shí)的圖片瑞佩,等圖片加載出來(lái)了再替換成要加載的圖片。
下面我們就來(lái)學(xué)習(xí)一下Glide占位圖功能的使用方法坯台,首先我事先準(zhǔn)備好了一張loading.jpg圖片炬丸,用來(lái)作為占位圖顯示。然后修改Glide加載部分的代碼蜒蕾,如下所示:
Glide.with(this)
.load(url)
.placeholder(R.drawable.loading)
.into(imageView);
沒(méi)錯(cuò)稠炬,就是這么簡(jiǎn)單。我們只是在剛才的三步走之間插入了一個(gè)placeholder()方法咪啡,然后將占位圖片的資源id傳入到這個(gè)方法中即可首启。另外,這個(gè)占位圖的用法其實(shí)也演示了Glide當(dāng)中絕大多數(shù)API的用法撤摸,其實(shí)就是在load()和into()方法之間串接任意想添加的功能就可以了毅桃。
不過(guò)如果你現(xiàn)在重新運(yùn)行一下代碼并點(diǎn)擊Load Image,很可能是根本看不到占位圖效果的愁溜。因?yàn)镚lide有非常強(qiáng)大的緩存機(jī)制疾嗅,我們剛才加載那張必應(yīng)美圖的時(shí)候Glide自動(dòng)就已經(jīng)將它緩存下來(lái)了,下次加載的時(shí)候?qū)?huì)直接從緩存中讀取冕象,不會(huì)再去網(wǎng)絡(luò)下載了代承,因而加載的速度非常快渐扮,所以占位圖可能根本來(lái)不及顯示论悴。
因此這里我們還需要稍微做一點(diǎn)修改,來(lái)讓占位圖能有機(jī)會(huì)顯示出來(lái)墓律,修改代碼如下所示:
Glide.with(this)
.load(url)
.placeholder(R.drawable.loading)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
可以看到膀估,這里串接了一個(gè)diskCacheStrategy()方法,并傳入DiskCacheStrategy.NONE參數(shù)耻讽,這樣就可以禁用掉Glide的緩存功能察纯。
關(guān)于Glide緩存方面的內(nèi)容我們將會(huì)在后面的文章進(jìn)行詳細(xì)的講解,這里只是為了測(cè)試占位圖功能而加的一個(gè)額外配置针肥,暫時(shí)你只需要知道禁用緩存必須這么寫就可以了饼记。
現(xiàn)在重新運(yùn)行一下代碼,效果如下圖所示:
可以看到慰枕,當(dāng)點(diǎn)擊Load Image按鈕之后會(huì)立即顯示一張占位圖具则,然后等真正的圖片加載完成之后會(huì)將占位圖替換掉。
當(dāng)然具帮,這只是占位圖的一種博肋,除了這種加載占位圖之外低斋,還有一種異常占位圖。異常占位圖就是指匪凡,如果因?yàn)槟承┊惓G闆r導(dǎo)致圖片加載失敗膊畴,比如說(shuō)手機(jī)網(wǎng)絡(luò)信號(hào)不好,這個(gè)時(shí)候就顯示這張異常占位圖病游。
異常占位圖的用法相信你已經(jīng)可以猜到了巴比,首先準(zhǔn)備一張error.jpg圖片,然后修改Glide加載部分的代碼礁遵,如下所示:
Glide.with(this)
.load(url)
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
很簡(jiǎn)單,這里又串接了一個(gè)error()方法就可以指定異常占位圖了采记。
現(xiàn)在你可以將圖片的url地址修改成一個(gè)不存在的圖片地址佣耐,或者干脆直接將手機(jī)的網(wǎng)絡(luò)給關(guān)了,然后重新運(yùn)行程序唧龄,效果如下圖所示:
這樣我們就把Glide提供的占位圖功能都掌握了兼砖。
指定圖片格式
我們還需要再了解一下Glide另外一個(gè)強(qiáng)大的功能,那就是Glide是支持加載GIF圖片的既棺。這一點(diǎn)確實(shí)非常牛逼讽挟,因?yàn)橄啾戎翵ake Warton曾經(jīng)明確表示過(guò),Picasso是不會(huì)支持加載GIF圖片的丸冕。
而使用Glide加載GIF圖并不需要編寫什么額外的代碼耽梅,Glide內(nèi)部會(huì)自動(dòng)判斷圖片格式。比如這是一張GIF圖片的URL地址:
http://p1.pstatp.com/large/166200019850062839d3
1
我們只需要將剛才那段加載圖片代碼中的URL地址替換成上面的地址就可以了胖烛,現(xiàn)在重新運(yùn)行一下代碼眼姐,效果如下圖所示:
也就是說(shuō),不管我們傳入的是一張普通圖片佩番,還是一張GIF圖片众旗,Glide都會(huì)自動(dòng)進(jìn)行判斷,并且可以正確地把它解析并展示出來(lái)趟畏。
但是如果我想指定圖片的格式該怎么辦呢贡歧?就比如說(shuō),我希望加載的這張圖必須是一張靜態(tài)圖片赋秀,我不需要Glide自動(dòng)幫我判斷它到底是靜圖還是GIF圖利朵。
想實(shí)現(xiàn)這個(gè)功能仍然非常簡(jiǎn)單,我們只需要再串接一個(gè)新的方法就可以了沃琅,如下所示:
Glide.with(this)
.load(url)
.asBitmap()
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
可以看到哗咆,這里在load()方法的后面加入了一個(gè)asBitmap()方法,這個(gè)方法的意思就是說(shuō)這里只允許加載靜態(tài)圖片益眉,不需要Glide去幫我們自動(dòng)進(jìn)行圖片格式的判斷了晌柬。
現(xiàn)在重新運(yùn)行一下程序姥份,效果如下圖所示:
由于調(diào)用了asBitmap()方法,現(xiàn)在GIF圖就無(wú)法正常播放了年碘,而是會(huì)在界面上顯示第一幀的圖片澈歉。
那么類似地,既然我們能強(qiáng)制指定加載靜態(tài)圖片屿衅,就也能強(qiáng)制指定加載動(dòng)態(tài)圖片埃难。比如說(shuō)我們想要實(shí)現(xiàn)必須加載動(dòng)態(tài)圖片的功能,就可以這樣寫:
Glide.with(this)
.load(url)
.asGif()
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
這里調(diào)用了asGif()方法替代了asBitmap()方法涤久,很好理解涡尘,相信不用我多做什么解釋了。
那么既然指定了只允許加載動(dòng)態(tài)圖片响迂,如果我們傳入了一張靜態(tài)圖片的URL地址又會(huì)怎么樣呢考抄?試一下就知道了,將圖片的URL地址改成剛才的必應(yīng)美圖蔗彤,然后重新運(yùn)行代碼川梅,效果如下圖所示。
沒(méi)錯(cuò)然遏,如果指定了只能加載動(dòng)態(tài)圖片贫途,而傳入的圖片卻是一張靜圖的話,那么結(jié)果自然就只有加載失敗嘍待侵。
指定圖片大小
實(shí)際上丢早,使用Glide在絕大多數(shù)情況下我們都是不需要指定圖片大小的。
在學(xué)習(xí)本節(jié)內(nèi)容之前诫给,你可能還需要先了解一個(gè)概念香拉,就是我們平時(shí)在加載圖片的時(shí)候很容易會(huì)造成內(nèi)存浪費(fèi)。什么叫內(nèi)存浪費(fèi)呢中狂?比如說(shuō)一張圖片的尺寸是1000*1000像素凫碌,但是我們界面上的ImageView可能只有200*200像素,這個(gè)時(shí)候如果你不對(duì)圖片進(jìn)行任何壓縮就直接讀取到內(nèi)存中胃榕,這就屬于內(nèi)存浪費(fèi)了盛险,因?yàn)槌绦蛑懈揪陀貌坏竭@么高像素的圖片。
關(guān)于圖片壓縮這方面勋又,我之前也翻譯過(guò)Android官方的一篇文章苦掘,感興趣的朋友可以去閱讀一下 Android高效加載大圖、多圖解決方案楔壤,有效避免程序OOM 鹤啡。
而使用Glide,我們就完全不用擔(dān)心圖片內(nèi)存浪費(fèi)蹲嚣,甚至是內(nèi)存溢出的問(wèn)題递瑰。因?yàn)镚lide從來(lái)都不會(huì)直接將圖片的完整尺寸全部加載到內(nèi)存中祟牲,而是用多少加載多少。Glide會(huì)自動(dòng)判斷ImageView的大小抖部,然后只將這么大的圖片像素加載到內(nèi)存當(dāng)中说贝,幫助我們節(jié)省內(nèi)存開(kāi)支。
當(dāng)然慎颗,Glide也并沒(méi)有使用什么神奇的魔法乡恕,它內(nèi)部的實(shí)現(xiàn)原理其實(shí)就是上面那篇文章當(dāng)中介紹的技術(shù),因此掌握了最基本的實(shí)現(xiàn)原理俯萎,你也可以自己實(shí)現(xiàn)一套這樣的圖片壓縮機(jī)制傲宜。
也正是因?yàn)镚lide是如此的智能,所以剛才在開(kāi)始的時(shí)候我就說(shuō)了夫啊,在絕大多數(shù)情況下我們都是不需要指定圖片大小的蛋哭,因?yàn)镚lide會(huì)自動(dòng)根據(jù)ImageView的大小來(lái)決定圖片的大小。
不過(guò)涮母,如果你真的有這樣的需求,必須給圖片指定一個(gè)固定的大小躁愿,Glide仍然是支持這個(gè)功能的叛本。修改Glide加載部分的代碼,如下所示:
Glide.with(this)
.load(url)
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.override(100, 100)
.into(imageView);
仍然非常簡(jiǎn)單彤钟,這里使用override()方法指定了一個(gè)圖片的尺寸来候,也就是說(shuō),Glide現(xiàn)在只會(huì)將圖片加載成100*100像素的尺寸逸雹,而不會(huì)管你的ImageView的大小是多少了营搅。