1. 程式人生 > >Glide完全解析(一)初步使用完全教程教程

Glide完全解析(一)初步使用完全教程教程

一、背景

現在Android上的圖片載入框架非常成熟,從最早的老牌圖片載入框架UniversalImageLoader,到後來Google推出的Volley,再到後來的新興軍Glide和Picasso,當然還有Facebook的Fresco。每一個都非常穩定,功能也都十分強大。但是它們的使用場景基本都是重合的,也就是說我們基本只需要選擇其中一個來進行學習和使用就足夠了,每一個框架都嘗試去掌握的話則有些浪費時間。

在這幾個框架當中,我對Volley和Glide研究得比較深入,對UniversalImageLoader、Picasso和Fresco都只是有一些基本的瞭解。從易用性上來講,Glide和Picasso應該都是完勝其他框架的,這兩個框架都實在是太簡單好用了,大多數情況下載入圖片都是一行程式碼就能解決的,而UniversalImageLoader和Fresco則在這方面略遜一些。

總之,沒有最好的框架,只有最適合自己的框架。經過多方面對比之後,我還是決定選擇了Glide來進行研究,並且這也是Google官方推薦的圖片載入框架。

之前在看郭霖大佬對於glide的原始碼分析,不得不說郭霖大佬寫部落格真的很詳細,理解也非常透徹,看完真的感覺很不錯,不過現在glide出了4.0版本,其原始碼對實現過程還是做了很大的調整,讓其可讀性和架構更加好,我試圖想通過自己的理解去寫完glide的實現原理,當然由於自己水平有限,時間也不充裕,可能不知道能不能寫完,也可能分析得不到位,可能還要借鑑大佬們的部落格,取其精華,去其糟粕,總之有一個好的開始才有可能寫成自己喜歡的部落格。

二、準備工作

要想使用Glide,首先需要將這個庫引入到我們的專案當中。新建一個Glide4Test專案,然後在app/build.gradle檔案當中新增如下依賴:

dependencies {
    implementation 'com.github.bumptech.glide:glide:4.4.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.4.0'
}

另外,Glide中需要用到網路功能,因此你還得在AndroidManifest.xml中宣告一下網路許可權才行:

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

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

三、簡單使用

然後我們想要在程式當中去載入這張圖片。

那麼首先開啟專案的佈局檔案,在佈局當中加入一個Button和一個ImageView,如下所示:

<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的時候能夠將剛才的圖片顯示在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://guolin.tech/book.png";
        Glide.with(this).load(url).into(imageView);
    }

}

沒錯,就是這麼簡單。現在我們來執行一下程式,效果如下圖所示:

這裡寫圖片描述

可以看到,一張網路上的圖片已經被成功下載,並且展示到ImageView上了。

你會發現,到目前為止,Glide 4的用法和Glide 3是完全一樣的,實際上核心的程式碼就只有這一行而已:

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

好了,現在你已經成功入門Glide 4了,那麼接下來就讓我們學習一下Glide 4的更多用法吧。

四、佔位圖

觀察剛才載入網路圖片的效果,你會發現,點選了Load Image按鈕之後,要稍微等一會圖片才會顯示出來。這其實很容易理解,因為從網路上下載圖片本來就是需要時間的。那麼我們有沒有辦法再優化一下使用者體驗呢?當然可以,Glide提供了各種各樣非常豐富的API支援,其中就包括了佔位圖功能。

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

下面我們就來學習一下Glide佔位圖功能的使用方法,首先我事先準備好了一張loading.jpg圖片,用來作為佔位圖顯示。然後修改Glide載入部分的程式碼,如下所示

RequestOptions options = new RequestOptions()
        .placeholder(R.drawable.loading);
Glide.with(this)
     .load(url)
     .apply(options)
     .into(imageView);

沒錯,就是這麼簡單。這裡我們先建立了一個RequestOptions物件,然後呼叫它的placeholder()方法來指定佔位圖,再將佔點陣圖片的資源id傳入到這個方法中。最後,在Glide的三步走之間加入一個apply()方法,來應用我們剛才建立的RequestOptions物件。

不過如果你現在重新執行一下程式碼並點選Load Image,很可能是根本看不到佔位圖效果的。因為Glide有非常強大的快取機制,我們剛才載入圖片的時候Glide自動就已經將它快取下來了,下次載入的時候將會直接從快取中讀取,不會再去網路下載了,因而載入的速度非常快,所以佔位圖可能根本來不及顯示。

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

RequestOptions options = new RequestOptions()
        .placeholder(R.drawable.loading)
        .diskCacheStrategy(DiskCacheStrategy.NONE);
Glide.with(this)
     .load(url)
     .apply(options)
     .into(imageView);

可以看到,這裡在RequestOptions物件中又串接了一個diskCacheStrategy()方法,並傳入DiskCacheStrategy.NONE引數,這樣就可以禁用掉Glide的快取功能。

關於Glide快取方面的內容我們待會兒會進行更詳細的講解,這裡只是為了測試佔位圖功能而加的一個額外配置,暫時你只需要知道禁用快取必須這麼寫就可以了。

現在重新執行一下程式碼,效果如下圖所示:

這裡寫圖片描述

可以看到,當點選Load Image按鈕之後會立即顯示一張佔位圖,然後等真正的圖片載入完成之後會將佔點陣圖替換掉。

除了這種載入佔位圖之外,還有一種異常佔位圖。異常佔位圖就是指,如果因為某些異常情況導致圖片載入失敗,比如說手機網路訊號不好,這個時候就顯示這張異常佔位圖。

異常佔位圖的用法相信你已經可以猜到了,首先準備一張error.jpg圖片,然後修改Glide載入部分的程式碼,如下所示:

RequestOptions options = new RequestOptions()
        .placeholder(R.drawable.ic_launcher_background)
        .error(R.drawable.error)
        .diskCacheStrategy(DiskCacheStrategy.NONE);
Glide.with(this)
     .load(url)
     .apply(options)
     .into(imageView);

很簡單,這裡又串接了一個error()方法就可以指定異常佔位圖了。

其實看到這裡,如果你熟悉Glide 3的話,相信你已經掌握Glide 4的變化規律了。在Glide 3當中,像placeholder()、error()、diskCacheStrategy()等等一系列的API,都是直接串聯在Glide三步走方法中使用的。

而Glide 4中引入了一個RequestOptions物件,將這一系列的API都移動到了RequestOptions當中。這樣做的好處是可以使我們擺脫冗長的Glide載入語句,而且還能進行自己的API封裝,因為RequestOptions是可以作為引數傳入到方法中的。

比如你就可以寫出這樣的Glide載入工具類:

public class GlideUtil {

    public static void load(Context context,
                            String url,
                            ImageView imageView,
                            RequestOptions options) {
        Glide.with(context)
             .load(url)
             .apply(options)
             .into(imageView);
    }

}

五、指定圖片大小

#

RequestOptions options = new RequestOptions()
        .override(200, 100);
Glide.with(this)
     .load(url)
     .apply(options)
     .into(imageView);

這樣的話,Glide就不會再去自動壓縮圖片,而是會去載入圖片的原始尺寸。當然,這種寫法也會面臨著更高的OOM風險。

六、快取機制

Glide的快取設計可以說是非常先進的,考慮的場景也很周全。在快取這一功能上,Glide又將它分成了兩個模組,一個是記憶體快取,一個是硬碟快取。

這兩個快取模組的作用各不相同,記憶體快取的主要作用是防止應用重複將圖片資料讀取到記憶體當中,而硬碟快取的主要作用是防止應用重複從網路或其他地方重複下載和讀取資料。

記憶體快取和硬碟快取的相互結合才構成了Glide極佳的圖片快取效果,那麼接下來我們就來分別學習一下這兩種快取的使用方法。

首先來看記憶體快取。

你要知道,預設情況下,Glide自動就是開啟記憶體快取的。也就是說,當我們使用Glide載入了一張圖片之後,這張圖片就會被快取到記憶體當中,只要在它還沒從記憶體中被清除之前,下次使用Glide再載入這張圖片都會直接從記憶體當中讀取,而不用重新從網路或硬碟上讀取了,這樣無疑就可以大幅度提升圖片的載入效率。比方說你在一個RecyclerView當中反覆上下滑動,RecyclerView中只要是Glide載入過的圖片都可以直接從記憶體當中迅速讀取並展示出來,從而大大提升了使用者體驗。

而Glide最為人性化的是,你甚至不需要編寫任何額外的程式碼就能自動享受到這個極為便利的記憶體快取功能,因為Glide預設就已經將它開啟了。

那麼既然已經預設開啟了這個功能,還有什麼可講的用法呢?只有一點,如果你有什麼特殊的原因需要禁用記憶體快取功能,Glide對此提供了介面:

RequestOptions options = new RequestOptions()
        .skipMemoryCache(true);
Glide.with(this)
     .load(url)
     .apply(options)
     .into(imageView);

可以看到,只需要呼叫skipMemoryCache()方法並傳入true,就表示禁用掉Glide的記憶體快取功能。

接下來我們開始學習硬碟快取方面的內容。

其實在剛剛學習佔位圖功能的時候,我們就使用過硬碟快取的功能了。當時為了禁止Glide對圖片進行硬碟快取而使用瞭如下程式碼:

RequestOptions options = new RequestOptions()
        .diskCacheStrategy(DiskCacheStrategy.NONE);
Glide.with(this)
     .load(url)
     .apply(options)
     .into(imageView);

呼叫diskCacheStrategy()方法並傳入DiskCacheStrategy.NONE,就可以禁用掉Glide的硬碟快取功能了。

這個diskCacheStrategy()方法基本上就是Glide硬碟快取功能的一切,它可以接收五種引數:

DiskCacheStrategy.NONE: 表示不快取任何內容。

DiskCacheStrategy.DATA: 表示只快取原始圖片。

DiskCacheStrategy.RESOURCE: 表示只快取轉換過後的圖片。

DiskCacheStrategy.ALL : 表示既快取原始圖片,也快取轉換過後的圖片。

DiskCacheStrategy.AUTOMATIC: 表示讓Glide根據圖片資源智慧地選擇使用哪一種快取策略(預設選項)。

其中,DiskCacheStrategy.DATA對應Glide 3中的DiskCacheStrategy.SOURCE,DiskCacheStrategy.RESOURCE對應Glide 3中的DiskCacheStrategy.RESULT。而DiskCacheStrategy.AUTOMATIC是Glide 4中新增的一種快取策略,並且在不指定diskCacheStrategy的情況下預設使用就是的這種快取策略。

上面五種引數的解釋本身並沒有什麼難理解的地方,但是關於轉換過後的圖片這個概念大家可能需要了解一下。就是當我們使用Glide去載入一張圖片的時候,Glide預設並不會將原始圖片展示出來,而是會對圖片進行壓縮和轉換(我們會在稍後學習這方面的內容)。總之就是經過種種一系列操作之後得到的圖片,就叫轉換過後的圖片。

七、指定載入格式

我們都知道,Glide其中一個非常亮眼的功能就是可以載入GIF圖片,而同樣作為非常出色的圖片載入框架的Picasso是不支援這個功能的。

而且使用Glide載入GIF圖並不需要編寫什麼額外的程式碼,Glide內部會自動判斷圖片格式。比如我們將載入圖片的URL地址改成一張GIF圖,如下所示:

Glide.with(this)
     .load("http://guolin.tech/test.gif")
     .into(imageView);

現在重新執行一下程式碼,效果如下圖所示:

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

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

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

Glide.with(this)
     .asBitmap()
     .load("http://guolin.tech/test.gif")
     .into(imageView);

可以看到,這裡在with()方法的後面加入了一個asBitmap()方法,這個方法的意思就是說這裡只允許載入靜態圖片,不需要Glide去幫我們自動進行圖片格式的判斷了。如果你傳入的還是一張GIF圖的話,Glide會展示這張GIF圖的第一幀,而不會去播放它。

熟悉Glide 3的朋友對asBitmap()方法肯定不會陌生對吧?但是千萬不要覺得這裡就沒有陷阱了,在Glide 3中的語法是先load()再asBitmap()的,而在Glide 4中是先asBitmap()再load()的。乍一看可能分辨不出來有什麼區別,但如果你寫錯了順序就肯定會報錯了。

那麼類似地,既然我們能強制指定載入靜態圖片,就也能強制指定載入動態圖片,對應的方法是asGif()。而Glide 4中又新增了asFile()方法和asDrawable()方法,分別用於強制指定檔案格式的載入和Drawable格式的載入,用法都比較簡單,就不再進行演示了。

八、回撥與監聽

1. into()方法

我們都知道Glide的into()方法中是可以傳入ImageView的。那麼into()方法還可以傳入別的引數嗎?我們可以讓Glide加載出來的圖片不顯示到ImageView上嗎?答案是肯定的,這就需要用到自定義Target功能。

Glide中的Target功能多樣且複雜,下面我就先簡單演示一種SimpleTarget的用法吧,程式碼如下所示:

SimpleTarget<Drawable> simpleTarget = new SimpleTarget<Drawable>() {
    @Override
    public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) {
        imageView.setImageDrawable(resource);
    }
};

public void loadImage(View view) {
    Glide.with(this)
         .load("http://guolin.tech/book.png")
         .into(simpleTarget);
}

這裡我們建立了一個SimpleTarget的例項,並且指定它的泛型是Drawable,然後重寫了onResourceReady()方法。在onResourceReady()方法中,我們就可以獲取到Glide加載出來的圖片物件了,也就是方法引數中傳過來的Drawable物件。有了這個物件之後你可以使用它進行任意的邏輯操作,這裡我只是簡單地把它顯示到了ImageView上。

SimpleTarget的實現建立好了,那麼只需要在載入圖片的時候將它傳入到into()方法中就可以了

2. preload()方法

Glide載入圖片雖說非常智慧,它會自動判斷該圖片是否已經有快取了,如果有的話就直接從快取中讀取,沒有的話再從網路去下載。但是如果我希望提前對圖片進行一個預載入,等真正需要載入圖片的時候就直接從快取中讀取,不想再等待慢長的網路載入時間了,這該怎麼辦呢?

不用擔心,Glide專門給我們提供了預載入的介面,也就是preload()方法,我們只需要直接使用就可以了。

preload()方法有兩個方法過載,一個不帶引數,表示將會載入圖片的原始尺寸,另一個可以通過引數指定載入圖片的寬和高。

preload()方法的用法也非常簡單,直接使用它來替換into()方法即可,如下所示:

Glide.with(this)
     .load("http://guolin.tech/book.png")
     .preload();

呼叫了預載入之後,我們以後想再去載入這張圖片就會非常快了,因為Glide會直接從快取當中去讀取圖片並顯示出來,程式碼如下所示:

Glide.with(this)
     .load("http://guolin.tech/book.png")
     .into(imageView);

3. submit()方法

submit()
submit(int width, int height)

其中submit()方法是用於下載原始尺寸的圖片,而submit(int width, int height)則可以指定下載圖片的尺寸。

這裡就以submit()方法來舉例。當呼叫了submit()方法後會立即返回一個FutureTarget物件,然後Glide會在後臺開始下載圖片檔案。接下來我們呼叫FutureTarget的get()方法就可以去獲取下載好的圖片檔案了,如果此時圖片還沒有下載完,那麼get()方法就會阻塞住,一直等到圖片下載完成才會有值返回。

下面我們通過一個例子來演示一下吧,程式碼如下所示:

public void downloadImage() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                String url = "http://www.guolin.tech/book.png";
                final Context context = getApplicationContext();
                FutureTarget<File> target = Glide.with(context)
                        .asFile()
                        .load(url)
                        .submit();
                final File imageFile = target.get();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(context, imageFile.getPath(), Toast.LENGTH_LONG).show();
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }).start();
}

這段程式碼稍微有一點點長,我帶著大家解讀一下。首先,submit()方法必須要用在子執行緒當中,因為剛才說了FutureTarget的get()方法是會阻塞執行緒的,因此這裡的第一步就是new了一個Thread。在子執行緒當中,我們先獲取了一個Application Context,這個時候不能再用Activity作為Context了,因為會有Activity銷燬了但子執行緒還沒執行完這種可能出現。

接下來就是Glide的基本用法,只不過將into()方法替換成了submit()方法,並且還使用了一個asFile()方法來指定載入格式。submit()方法會返回一個FutureTarget物件,這個時候其實Glide已經開始在後臺下載圖片了,我們隨時都可以呼叫FutureTarget的get()方法來獲取下載的圖片檔案,只不過如果圖片還沒下載好執行緒會暫時阻塞住,等下載完成了才會把圖片的File物件返回。

最後,我們使用runOnUiThread()切回到主執行緒,然後使用Toast將下載好的圖片檔案路徑顯示出來。

現在重新執行一下程式碼,效果如下圖所示。

這裡寫圖片描述

4. listener()方法

其實listener()方法的作用非常普遍,它可以用來監聽Glide載入圖片的狀態。舉個例子,比如說我們剛才使用了preload()方法來對圖片進行預載入,但是我怎樣確定預載入有沒有完成呢?還有如果Glide載入圖片失敗了,我該怎樣除錯錯誤的原因呢?答案都在listener()方法當中。

下面來看下listener()方法的基本用法吧,不同於剛才幾個方法都是要替換into()方法的,listener()是結合into()方法一起使用的,當然也可以結合preload()方法一起使用。最基本的用法如下所示:

Glide.with(this)
     .load("http://www.guolin.tech/book.png")
     .listener(new RequestListener<Drawable>() {
         @Override
         public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
             return false;
         }

         @Override
         public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
             return false;
         }
     })
     .into(imageView);

這裡我們在into()方法之前串接了一個listener()方法,然後實現了一個RequestListener的例項。其中RequestListener需要實現兩個方法,一個onResourceReady()方法,一個onLoadFailed()方法。從方法名上就可以看出來了,當圖片載入完成的時候就會回撥onResourceReady()方法,而當圖片載入失敗的時候就會回撥onLoadFailed()方法,onLoadFailed()方法中會將失敗的GlideException引數傳進來,這樣我們就可以定位具體失敗的原因了。

沒錯,listener()方法就是這麼簡單。不過還有一點需要處理,onResourceReady()方法和onLoadFailed()方法都有一個布林值的返回值,返回false就表示這個事件沒有被處理,還會繼續向下傳遞,返回true就表示這個事件已經被處理掉了,從而不會再繼續向下傳遞。舉個簡單點的例子,如果我們在RequestListener的onResourceReady()方法中返回了true,那麼就不會再回調Target的onResourceReady()方法了。

九、圖片變換

圖片變換的意思就是說,Glide從載入了原始圖片到最終展示給使用者之前,又進行了一些變換處理,從而能夠實現一些更加豐富的圖片效果,如圖片圓角化、圓形化、模糊化等等。

新增圖片變換的用法非常簡單,我們只需要在RequestOptions中串接transforms()方法,並將想要執行的圖片變換操作作為引數傳入transforms()方法即可,如下所示:

RequestOptions options = new RequestOptions()
        .transforms(...);
Glide.with(this)
     .load(url)
     .apply(options)
     .into(imageView);

至於具體要進行什麼樣的圖片變換操作,這個通常都是需要我們自己來寫的。不過Glide已經內建了幾種圖片變換操作,我們可以直接拿來使用,比如CenterCrop、FitCenter、CircleCrop等。

但所有的內建圖片變換操作其實都不需要使用transform()方法,Glide為了方便我們使用直接提供了現成的API:


RequestOptions options = new RequestOptions()
        .centerCrop();

RequestOptions options = new RequestOptions()
        .fitCenter();

RequestOptions options = new RequestOptions()
        .circleCrop();

當然,這些內建的圖片變換API其實也只是對transform()方法進行了一層封裝而已,它們背後的原始碼仍然還是藉助transform()方法來實現的。

這裡我們就選擇其中一種內建的圖片變換操作來演示一下吧,circleCrop()方法是用來對圖片進行圓形化裁剪的,我們動手試一下,程式碼如下所示:

String url = "http://guolin.tech/book.png";
RequestOptions options = new RequestOptions()
        .circleCrop();
Glide.with(this)
     .load(url)
     .apply(options)
     .into(imageView);

重新執行一下程式並點選載入圖片按鈕,效果如下圖所示。

這裡寫圖片描述

可以看到,現在展示的圖片是對原圖進行圓形化裁剪後得到的圖片。

當然,除了使用內建的圖片變換操作之外,我們完全可以自定義自己的圖片變換操作。理論上,在對圖片進行變換這個步驟中我們可以進行任何的操作,你想對圖片怎麼樣都可以。包括圓角化、圓形化、黑白化、模糊化等等,甚至你將原圖片完全替換成另外一張圖都是可以的。

關於圖片變換,最後我們再來看一個非常優秀的開源庫,glide-transformations。它實現了很多通用的圖片變換效果,如裁剪變換、顏色變換、模糊變換等等,使得我們可以非常輕鬆地進行各種各樣的圖片變換。

下面我們就來體驗一下這個庫的強大功能吧。首先需要將這個庫引入到我們的專案當中,在app/build.gradle檔案當中新增如下依賴:

dependencies {
    implementation 'jp.wasabeef:glide-transformations:3.0.1'
}

我們可以對圖片進行單個變換處理,也可以將多種圖片變換疊加在一起使用。比如我想同時對圖片進行模糊化和黑白化處理,就可以這麼寫:

String url = "http://guolin.tech/book.png";
RequestOptions options = new RequestOptions()
        .transforms(new BlurTransformation(), new GrayscaleTransformation());
Glide.with(this)
     .load(url)
     .apply(options)
     .into(imageView);

可以看到,同時執行多種圖片變換的時候,只需要將它們都傳入到transforms()方法中即可。現在重新執行一下程式,效果如下圖所示

這裡寫圖片描述

十、自定義模組

自定義模組屬於Glide中的高階功能,同時也是難度比較高的一部分內容。

自定義模組功能可以將更改Glide配置,替換Glide元件等操作獨立出來,使得我們能輕鬆地對Glide的各種配置進行自定義,並且又和Glide的圖片載入邏輯沒有任何交集,這也是一種低耦合程式設計方式的體現。下面我們就來學習一下自定義模組要如何實現。

首先定義一個我們自己的模組類,並讓它繼承自AppGlideModule,如下所示:

@GlideModule
public class MyAppGlideModule extends AppGlideModule {

    @Override
    public void applyOptions(Context context, GlideBuilder builder) {

    }

    @Override
    public void registerComponents(Context context, Glide glide, Registry registry) {

    }

}

可以看到,在MyAppGlideModule類當中,我們重寫了applyOptions()和registerComponents()方法,這兩個方法分別就是用來更改Glide配置以及替換Glide元件的。

注意在MyAppGlideModule類在上面,我們加入了一個@GlideModule的註解,這是Gilde 4和Glide 3最大的一個不同之處。在Glide 3中,我們定義了自定義模組之後,還必須在AndroidManifest.xml檔案中去註冊它才能生效,而在Glide 4中是不需要的,因為@GlideModule這個註解已經能夠讓Glide識別到這個自定義模組了。

Generated API是Glide 4中全新引入的一個功能,它的工作原理是使用註解處理器 (Annotation Processor) 來生成出一個API,在Application模組中可使用該流式API一次性呼叫到RequestBuilder,RequestOptions和整合庫中所有的選項。

這麼解釋有點拗口,簡單點說,就是Glide 4仍然給我們提供了一套和Glide 3一模一樣的流式API介面。畢竟有些人還是覺得Glide 3的API更好用一些,比如說我。

Generated API對於熟悉Glide 3的朋友來說那是再簡單不過了,基本上就是和Glide 3一模一樣的用法,只不過需要把Glide關鍵字替換成GlideApp關鍵字,如下所示:


GlideApp.with(this)
        .load(url)
        .placeholder(R.drawable.loading)
        .error(R.drawable.error)
        .skipMemoryCache(true)
        .diskCacheStrategy(DiskCacheStrategy.NONE)
        .override(Target.SIZE_ORIGINAL)
        .circleCrop()
        .into(imageView);

不過,有可能你的IDE中會提示找不到GlideApp這個類。這個類是通過編譯時註解自動生成的,首先確保你的程式碼中有一個自定義的模組,並且給它加上了@GlideModule註解,也就是我們在上一節所講的內容。然後在Android Studio中點選選單欄Build -> Rebuild Project,GlideApp這個類就會自動生成了。

當然,Generated API所能做到的並不只是這些而已,它還可以對現有的API進行擴充套件,定製出任何屬於你自己的API。

下面我來具體舉個例子,比如說我們要求專案中所有圖片的快取策略全部都要快取原始圖片,那麼每次在使用Glide載入圖片的時候,都去指定diskCacheStrategy(DiskCacheStrategy.DATA)這麼長長的一串程式碼,確實是讓人比較心煩。這種情況我們就可以去定製一個自己的API了。

定製自己的API需要藉助@GlideExtension和@GlideOption這兩個註解。建立一個我們自定義的擴充套件類,程式碼如下所示:

###@GlideExtension
public class MyGlideExtension {

    private MyGlideExtension() {

    }

    @GlideOption
    public static void cacheSource(RequestOptions options) {
        options.diskCacheStrategy(DiskCacheStrategy.DATA);
    }

}

這裡我們定義了一個MyGlideExtension類,並且給加上了一個@GlideExtension註解,然後要將這個類的建構函式宣告成private,這都是必須要求的寫法。

接下來就可以開始自定義API了,這裡我們定義了一個cacheSource()方法,表示只快取原始圖片,並給這個方法加上了@GlideOption註解。注意自定義API的方法都必須是靜態方法,而且第一個引數必須是RequestOptions,後面你可以加入任意多個你想自定義的引數。

在cacheSource()方法中,我們仍然還是呼叫的diskCacheStrategy(DiskCacheStrategy.DATA)方法,所以說cacheSource()就是一層簡化API的封裝而已。

然後在Android Studio中點選選單欄Build -> Rebuild Project,神奇的事情就會發生了,你會發現你已經可以使用這樣的語句來載入圖片了:

GlideApp.with(this)
        .load(url)
        .cacheSource()
        .into(imageView);

有了這個強大的功能之後,我們使用Glide就能變得更加靈活了。

十二、結束語

這樣我們基本上就將Glide 4的所有重要內容都介紹完了,如果你以前非常熟悉Glide 3的話,看完這篇文章之後相信你已經能夠熟練使用Glide 4了。

相關推薦

Glide完全解析初步使用完全教程教程

一、背景 現在Android上的圖片載入框架非常成熟,從最早的老牌圖片載入框架UniversalImageLoader,到後來Google推出的Volley,再到後來的新興軍Glide和Picasso,當然還有Facebook的Fresco。每一個都非常穩

Android 開源框架Universal-Image-Loader完全解析--- 基本介紹及使用

                大家好!差不多兩個來月沒有寫文章了,前段時間也是在忙換工作的事,準備筆試面試什麼的事情,現在新工作找好了,新工作自己也比較滿意,唯一遺憾的就是自己要去一個新的城市,新的環境新的開始,希望自己能儘快的適應新環境,現在在準備交接的事情,自己也有一些時間了,所以就繼續給大家分享And

Android 網路通訊框架Volley完全解析

Volley簡介及Request基本用法  Google I/O 2013上,Volley釋出了。Volley是Android平臺上的網路通訊庫,能使網路通訊更快,更簡單,更健壯。這是Volley名

Android硬編解碼介面MediaCodec使用完全解析

由於4月初要離職了,在找新工作,發現很多企業的招聘資訊都有“附上自己的技術部落格可以加分”類似的說明,正好最後的這段時間會比較閒,所以打算整理一下以前記錄的一些筆記發上來,也算是回顧一下。由於這些筆記或多或少的參考了其他資料,所以本人不擁有其版權,可以隨便

Java上傳下載完全解析

  在Java Web開發中,經常會用到上傳與下載檔案,典型的案例即為伺服器獲取上傳的檔案,將其儲存至本地,並獲取其下載的檔案url,客戶端在獲取下載的url後,在伺服器進行下載。下面我們就來說一下Java中檔案的上傳。   一、設定CommonsMultipartReso

Android Fragment 真正的完全解析

watermark 展示 near 主界面 ddt comm 講解 超級 pro 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/lmj623565791/article/details/37970961 轉載請標明出處:

嵌入式Linux應用開發完全手冊嵌入式Linux基礎知識

嵌入式Linux應用開發完全手冊 3 嵌入式Linux基礎知識 3.1 交叉編譯工具 編譯工具鏈,編譯工作由幾個步驟完成,分別用到了不同的工具 PC端應用 gcc ld objcopy

嵌入式linux應用開發完全手冊

第一篇 嵌入式Linux開發環境構建 1.1.2 嵌入式發展 SCM(Single Chip Microcomputer)微控制器; MCU(Micro Controller Unit)微控制器; SoC(System on a Chip):系統級晶片,在一個晶片上由於廣泛使用

Android 屬性動畫Property Animation 完全解析 【轉】

轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/38067475 1、概述 Android提供了幾種動畫型別:View Animation 、Drawable Animation 、Property Anima

【Android自助餐】Handler訊息機制完全解析MessageQueue的佇列管理

Android自助餐Handler訊息機制完全解析(二)MessageQueue的佇列管理 Android自助餐Handler訊息機制完全解析二MessageQueue的佇列管理 新增到訊息佇列enqueueMessage 從佇

【Android自助餐】Handler訊息機制完全解析鳥瞰與總結

Android自助餐Handler訊息機制完全解析(五)鳥瞰與總結 Android自助餐Handler訊息機制完全解析五鳥瞰與總結 Message MessageQueue Handler Looper

【Android自助餐】Handler訊息機制完全解析Looper解析

Android自助餐Handler訊息機制完全解析(四)Looper解析 Android自助餐Handler訊息機制完全解析四Looper解析 Looper 初始化prepare 提供loope

Android進階——效能優化之程序拉活原理及手段完全解析

引言 上一篇文章Android進階——效能優化之程序保活原理及手段完全解析(一)總結了Android程序和執行緒的相關知識,主要介紹了幾種提升程序優先順序的手段,通常僅僅是提高優先順序只能讓你的程序存活時間久一點,但是真正的被殺死之後就不會自動拉活的,如果你的程

Android安全攻防戰,反編譯與混淆技術完全解析

轉載請註明出處:http://blog.csdn.net/guolin_blog/article/details/49738023 之前一直有猶豫過要不要寫這篇文章,畢竟去反編譯人家的程式並不是什麼值得驕傲的事情。不過單純從技術角度上來講,掌握反編譯功能確實是

Android圖片載入框架最全解析Glide的基本用法

現在Android上的圖片載入框架非常成熟,從最早的老牌圖片載入框架UniversalImageLoader,到後來Google推出的Volley,再到後來的新興軍Glide和Picasso,當然還有Facebook的Fresco。每一個都非常穩定,功能也都十分強大。但是它們

Android圖片載入框架最全解析Glide的基本用法

現在Android上的圖片載入框架非常成熟,從最早的老牌圖片載入框架UniversalImageLoader,到後來Google推出的Volley,再到後來的新興軍Glide和Picasso,當然還有Facebook的Fresco。每一個都非常穩定,功能也都

OkHtto完全解析構建和呼叫

要求基於Java 7構建和執行,執行時需相容Java 6確保 Android平臺和舊版本JVM的穩定性。 2.1 通過Maven進行桌面測試 通過Maven在桌面上執行OkHttp測試程式。使用Jetty-ALPN在桌面上執行HTTP/2和SPDY的測試程式。 mvn cl

ORMLite完全解析官方文件第三章、自定義查詢構造器 Custom Query Builder

          接著上一篇,下面是第三章的翻譯整理,理解錯誤的地方還請批評指正。  第三章、 自定義查詢構造器 3.1  查詢構造器基礎       下面是使用查詢構造器建立自定義查詢語句的基本步驟。首先,以java常量的形式為屬性設定列名,便於使用它 們進行

OkHttp完全解析攔截器

攔截器是一種能夠監控,重寫,重試呼叫的強大機制。 呼叫chain.proceed(request)是每個攔截器實現的關鍵部分。這個看似簡單的方法是所有HTTP 工作發生的地方, 在這裡產生一個響應應答請求。 攔截器可以是鏈式的,假設你有一個壓縮攔截器和一個校驗攔截器,那

OkHttp完全解析HTTPS

OkHttp試圖平衡連個相互競爭的問題: 儘可能多的主機連線: 包括執行最新版boringssl的高階主機和執行老版OpenSSL的陳舊主機。 連線的安全性: 通過證書進行遠端web伺服器驗證和通過強加密保證資料交換的私密性。 當與一個HTTPS伺服器進行協商時, OkHt