Android圖片加載之Glide的詳解及基本用法

開(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的大小是多少了营搅。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市梆砸,隨后出現(xiàn)的幾起案子转质,更是在濱河造成了極大的恐慌,老刑警劉巖帖世,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件休蟹,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡日矫,警方通過(guò)查閱死者的電腦和手機(jī)赂弓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)哪轿,“玉大人盈魁,你說(shuō)我怎么就攤上這事∏运撸” “怎么了杨耙?”我有些...
    開(kāi)封第一講書人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵赤套,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我按脚,道長(zhǎng)于毙,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任辅搬,我火速辦了婚禮唯沮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘堪遂。我一直安慰自己介蛉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布溶褪。 她就那樣靜靜地躺著币旧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪猿妈。 梳的紋絲不亂的頭發(fā)上吹菱,一...
    開(kāi)封第一講書人閱讀 52,475評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音彭则,去河邊找鬼鳍刷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛俯抖,可吹牛的內(nèi)容都是我干的输瓜。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼芬萍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼尤揣!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起柬祠,我...
    開(kāi)封第一講書人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤北戏,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后漫蛔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體最欠,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年惩猫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了芝硬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡轧房,死狀恐怖拌阴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情奶镶,我是刑警寧澤迟赃,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布陪拘,位于F島的核電站,受9級(jí)特大地震影響纤壁,放射性物質(zhì)發(fā)生泄漏左刽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一酌媒、第九天 我趴在偏房一處隱蔽的房頂上張望欠痴。 院中可真熱鬧,春花似錦秒咨、人聲如沸喇辽。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)菩咨。三九已至,卻和暖如春陡厘,著一層夾襖步出監(jiān)牢的瞬間抽米,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工糙置, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缨硝,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓罢低,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親胖笛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子网持,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361