「轉(zhuǎn)載」Android圖片加載框架最全解析(一),Glide的基本用法

轉(zhuǎn)至 郭霖CSDN博客 http://blog.csdn.net/guolin_blog/article/details/53759439

開始

Glide是一款由Bump Technologies開發(fā)的圖片加載框架,使得我們可以在android平臺上以極度簡單的方式加載和展示圖片。

目前,Glide最新的穩(wěn)定版本是3.7.0,雖然3.8.0已經(jīng)推出預(yù)覽版了,但是暫時問題還比較多。因此,我們這個系列的博客都會使用Glide 3.7.0版本來進行講解,這個版本的Glide相當成熟和穩(wěn)定。

要想使用Glide,首先需要將這個庫引入到我們的項目當中。新建一個GlideTest項目,然后在app/build.gradle文件當中添加如下依賴:

dependencies {
    compile 'com.github.bumptech.glide:glide:3.7.0'
}

另外,Glide中需要用到網(wǎng)絡(luò)功能,因此你還得在AndroidManifest.xml中聲明一下網(wǎng)絡(luò)權(quán)限才行:

<uses-permission android:name="android.permission.INTERNET" />

就是這么簡單,然后我們就可以自由地使用Glide中的任意功能了。

加載圖片

現(xiàn)在我們就來嘗試一下如何使用Glide來加載圖片吧。比如這是必應(yīng)上一張首頁美圖的地址:

http://cn.bing.com/az/hprichbg/rb/Dongdaemun_ZH-CN10736487148_1920x1080.jpg

然后我們想要在程序當中去加載這張圖片。

那么首先打開項目的布局文件,在布局當中加入一個Button和一個ImageView,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="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>

為了讓用戶點擊Button的時候能夠?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);
    }
}

沒錯,就是這么簡單?,F(xiàn)在我們來運行一下程序,效果如下圖所示:

可以看到,一張網(wǎng)絡(luò)上的圖片已經(jīng)被成功下載,并且展示到ImageView上了。
而我們到底做了什么?實際上核心的代碼就只有這一行而已:

Glide.with(this).load(url).into(imageView);

千萬不要小看這一行代碼,實際上僅僅就這一行代碼,你已經(jīng)可以做非常非常多的事情了,包括加載網(wǎng)絡(luò)上的圖片、加載手機本地的圖片、加載應(yīng)用資源中的圖片等等。

下面我們就來詳細解析一下這行代碼。

首先,調(diào)用Glide.with()方法用于創(chuàng)建一個加載圖片的實例。with()方法可以接收Context、Activity或者Fragment類型的參數(shù)。也就是說我們選擇的范圍非常廣,不管是在Activity還是Fragment中調(diào)用with()方法,都可以直接傳this。那如果調(diào)用的地方既不在Activity中也不在Fragment中呢?也沒關(guān)系,我們可以獲取當前應(yīng)用程序的ApplicationContext,傳入到with()方法當中。注意with()方法中傳入的實例會決定Glide加載圖片的生命周期,如果傳入的是Activity或者Fragment的實例,那么當這個Activity或Fragment被銷毀的時候,圖片加載也會停止。如果傳入的是ApplicationContext,那么只有當應(yīng)用程序被殺掉的時候,圖片加載才會停止。

接下來看一下load()方法,這個方法用于指定待加載的圖片資源。Glide支持加載各種各樣的圖片資源,包括網(wǎng)絡(luò)圖片、本地圖片、應(yīng)用資源、二進制流、Uri對象等等。因此load()方法也有很多個方法重載,除了我們剛才使用的加載一個字符串網(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);

// 加載二進制流
byte[] image = getImageBytes();
Glide.with(this).load(image).into(imageView);

// 加載Uri對象
Uri imageUri = getImageUri();
Glide.with(this).load(imageUri).into(imageView);

最后看一下into()方法,這個方法就很簡單了,我們希望讓圖片顯示在哪個ImageView上,把這個ImageView的實例傳進去就可以了。當然,into()方法不僅僅是只能接收ImageView類型的參數(shù),還支持很多更豐富的用法,不過那個屬于高級技巧,我們會在后面的文章當中學(xué)習(xí)。

那么回顧一下Glide最基本的使用方式,其實就是關(guān)鍵的三步走:先with(),再load(),最后into()。熟記這三步,你就已經(jīng)入門Glide了。

占位圖

現(xiàn)在我們來學(xué)一些Glide的擴展內(nèi)容。其實剛才所學(xué)的三步走就是Glide最核心的東西,而我們后面所要學(xué)習(xí)的所有東西都是在這個三步走的基礎(chǔ)上不斷進行擴展而已。

觀察剛才加載網(wǎng)絡(luò)圖片的效果,你會發(fā)現(xiàn),點擊了Load Image按鈕之后,要稍微等一會圖片才會顯示出來。這其實很容易理解,因為從網(wǎng)絡(luò)上下載圖片本來就是需要時間的。那么我們有沒有辦法再優(yōu)化一下用戶體驗?zāi)兀慨斎豢梢?,Glide提供了各種各樣非常豐富的API支持,其中就包括了占位圖功能。

顧名思義,占位圖就是指在圖片的加載過程中,我們先顯示一張臨時的圖片,等圖片加載出來了再替換成要加載的圖片。

下面我們就來學(xué)習(xí)一下Glide占位圖功能的使用方法,首先我事先準備好了一張loading.jpg圖片,用來作為占位圖顯示。然后修改Glide加載部分的代碼,如下所示:

Glide.with(this)
     .load(url)
     .placeholder(R.drawable.loading)
     .into(imageView);

沒錯,就是這么簡單。我們只是在剛才的三步走之間插入了一個placeholder()方法,然后將占位圖片的資源id傳入到這個方法中即可。另外,這個占位圖的用法其實也演示了Glide當中絕大多數(shù)API的用法,其實就是在load()和into()方法之間串接任意想添加的功能就可以了。

不過如果你現(xiàn)在重新運行一下代碼并點擊Load Image,很可能是根本看不到占位圖效果的。因為Glide有非常強大的緩存機制,我們剛才加載那張必應(yīng)美圖的時候Glide自動就已經(jīng)將它緩存下來了,下次加載的時候?qū)苯訌木彺嬷凶x取,不會再去網(wǎng)絡(luò)下載了,因而加載的速度非??欤哉嘉粓D可能根本來不及顯示。

因此這里我們還需要稍微做一點修改,來讓占位圖能有機會顯示出來,修改代碼如下所示:

Glide.with(this)
     .load(url)
     .placeholder(R.drawable.loading)
     .diskCacheStrategy(DiskCacheStrategy.NONE)
     .into(imageView);

可以看到,這里串接了一個diskCacheStrategy()方法,并傳入DiskCacheStrategy.NONE參數(shù),這樣就可以禁用掉Glide的緩存功能。
關(guān)于Glide緩存方面的內(nèi)容我們將會在后面的文章進行詳細的講解,這里只是為了測試占位圖功能而加的一個額外配置,暫時你只需要知道禁用緩存必須這么寫就可以了。
現(xiàn)在重新運行一下代碼,效果如下圖所示:

可以看到,當點擊Load Image按鈕之后會立即顯示一張占位圖,然后等真正的圖片加載完成之后會將占位圖替換掉。

當然,這只是占位圖的一種,除了這種加載占位圖之外,還有一種異常占位圖。異常占位圖就是指,如果因為某些異常情況導(dǎo)致圖片加載失敗,比如說手機網(wǎng)絡(luò)信號不好,這個時候就顯示這張異常占位圖。

異常占位圖的用法相信你已經(jīng)可以猜到了,首先準備一張error.jpg圖片,然后修改Glide加載部分的代碼,如下所示:

Glide.with(this)
     .load(url)
     .placeholder(R.drawable.loading)
     .error(R.drawable.error)
     .diskCacheStrategy(DiskCacheStrategy.NONE)
     .into(imageView);

很簡單,這里又串接了一個error()方法就可以指定異常占位圖了。
現(xiàn)在你可以將圖片的url地址修改成一個不存在的圖片地址,或者干脆直接將手機的網(wǎng)絡(luò)給關(guān)了,然后重新運行程序,效果如下圖所示:

這樣我們就把Glide提供的占位圖功能都掌握了。

指定圖片格式

我們還需要再了解一下Glide另外一個強大的功能,那就是Glide是支持加載GIF圖片的。這一點確實非常牛逼,因為相比之下Jake Warton曾經(jīng)明確表示過,Picasso是不會支持加載GIF圖片的。

而使用Glide加載GIF圖并不需要編寫什么額外的代碼,Glide內(nèi)部會自動判斷圖片格式。比如這是一張GIF圖片的URL地址:

http://p1.pstatp.com/large/166200019850062839d3

我們只需要將剛才那段加載圖片代碼中的URL地址替換成上面的地址就可以了,現(xiàn)在重新運行一下代碼,效果如下圖所示:

也就是說,不管我們傳入的是一張普通圖片,還是一張GIF圖片,Glide都會自動進行判斷,并且可以正確地把它解析并展示出來。

但是如果我想指定圖片的格式該怎么辦呢?就比如說,我希望加載的這張圖必須是一張靜態(tài)圖片,我不需要Glide自動幫我判斷它到底是靜圖還是GIF圖。

想實現(xiàn)這個功能仍然非常簡單,我們只需要再串接一個新的方法就可以了,如下所示:

Glide.with(this)
     .load(url)
     .asBitmap()
     .placeholder(R.drawable.loading)
     .error(R.drawable.error)
     .diskCacheStrategy(DiskCacheStrategy.NONE)
     .into(imageView);

可以看到,這里在load()方法的后面加入了一個asBitmap()方法,這個方法的意思就是說這里只允許加載靜態(tài)圖片,不需要Glide去幫我們自動進行圖片格式的判斷了。
現(xiàn)在重新運行一下程序,效果如下圖所示:

由于調(diào)用了asBitmap()方法,現(xiàn)在GIF圖就無法正常播放了,而是會在界面上顯示第一幀的圖片。
那么類似地,既然我們能強制指定加載靜態(tài)圖片,就也能強制指定加載動態(tài)圖片。比如說我們想要實現(xiàn)必須加載動態(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()方法,很好理解,相信不用我多做什么解釋了。
那么既然指定了只允許加載動態(tài)圖片,如果我們傳入了一張靜態(tài)圖片的URL地址又會怎么樣呢?試一下就知道了,將圖片的URL地址改成剛才的必應(yīng)美圖,然后重新運行代碼,效果如下圖所示。

沒錯,如果指定了只能加載動態(tài)圖片,而傳入的圖片卻是一張靜圖的話,那么結(jié)果自然就只有加載失敗嘍。

指定圖片大小

實際上,使用Glide在絕大多數(shù)情況下我們都是不需要指定圖片大小的。

在學(xué)習(xí)本節(jié)內(nèi)容之前,你可能還需要先了解一個概念,就是我們平時在加載圖片的時候很容易會造成內(nèi)存浪費。什么叫內(nèi)存浪費呢?比如說一張圖片的尺寸是1000 × 1000像素,但是我們界面上的ImageView可能只有200 × 200像素,這個時候如果你不對圖片進行任何壓縮就直接讀取到內(nèi)存中,這就屬于內(nèi)存浪費了,因為程序中根本就用不到這么高像素的圖片。

關(guān)于圖片壓縮這方面,我之前也翻譯過Android官方的一篇文章,感興趣的朋友可以去閱讀一下 Android高效加載大圖、多圖解決方案,有效避免程序OOM 。

而使用Glide,我們就完全不用擔心圖片內(nèi)存浪費,甚至是內(nèi)存溢出的問題。因為Glide從來都不會直接將圖片的完整尺寸全部加載到內(nèi)存中,而是用多少加載多少。Glide會自動判斷ImageView的大小,然后只將這么大的圖片像素加載到內(nèi)存當中,幫助我們節(jié)省內(nèi)存開支。

當然,Glide也并沒有使用什么神奇的魔法,它內(nèi)部的實現(xiàn)原理其實就是上面那篇文章當中介紹的技術(shù),因此掌握了最基本的實現(xiàn)原理,你也可以自己實現(xiàn)一套這樣的圖片壓縮機制。

也正是因為Glide是如此的智能,所以剛才在開始的時候我就說了,在絕大多數(shù)情況下我們都是不需要指定圖片大小的,因為Glide會自動根據(jù)ImageView的大小來決定圖片的大小。

不過,如果你真的有這樣的需求,必須給圖片指定一個固定的大小,Glide仍然是支持這個功能的。修改Glide加載部分的代碼,如下所示:

Glide.with(this)
     .load(url)
     .placeholder(R.drawable.loading)
     .error(R.drawable.error)
     .diskCacheStrategy(DiskCacheStrategy.NONE)
     .override(100, 100)
     .into(imageView);

仍然非常簡單,這里使用override()方法指定了一個圖片的尺寸,也就是說,Glide現(xiàn)在只會將圖片加載成100*100像素的尺寸,而不會管你的ImageView的大小是多少了。

好了,今天是我們這個Glide系列的第一篇文章,寫了這么多內(nèi)容已經(jīng)算是挺不錯的了?,F(xiàn)在你已經(jīng)了解了Glide的基本用法,當然也是一些最常用的用法。下一篇文章當中,我們會嘗試去分析Glide的源碼,研究一下在這些基本用法的背后,Glide到底執(zhí)行了什么神奇的操作,能夠使得我們加載圖片變得這么簡單?感興趣的朋友請繼續(xù)閱讀 Android圖片加載框架最全解析(二),從源碼的角度理解Glide的執(zhí)行流程 。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Glide是一款由Bump Technologies開發(fā)的圖片加載框架,使得我們可以在Android平臺上以極度簡...
    GB_speak閱讀 1,161評論 6 11
  • 作者簡介 原創(chuàng)微信公眾號郭霖 WeChat ID: guolin_blog 現(xiàn)在Android上的圖片加載框架非常...
    木木00閱讀 4,301評論 1 17
  • 雜草、小花、陳舊的木門、斑駁的樹影、石塊鋪就的小路…所以這些意象都給我以莫名而又強烈的親切感。在上個世紀的中國...
    梨花兼著芭蕉閱讀 348評論 0 0
  • 唐朝時,有個美男子,名字喚作白衣,出身名門。他溫文爾雅的氣質(zhì),眉清目秀的臉龐,又有吟詩作對的才華,在唐朝,擁有了...
    一只特立獨行的豬與阿飛閱讀 415評論 8 7
  • 做IOS開發(fā)也有兩年了,記得第一次接觸IOS時,碰到的第一個問題就是這個證書,稀里糊涂的把攔路的問題搞定后,也沒有...
    奮拓達閱讀 571評論 0 5