Glide內(nèi)部HTTP通訊組件的底層實現(xiàn)是基于HttpUrlConnection來進(jìn)行定制的。但是HttpUrlConnection的可擴展性比較有限盐股,因此我們今天介紹如何將Glide中的HTTP通訊組件替換成OkHttp。
一欲侮、前言
在Glide v3
中攒驰,當(dāng)我們創(chuàng)建好一個自定義模塊之后,還必須在AndroidManifest.xml文件中注冊它才能生效茬斧。隨著Glide框架的不斷優(yōu)化腰懂,在Glide v4
中我們只需要使用@GlideModule
這個注解就能夠讓Glide輕輕松松識別到我們創(chuàng)建的自定義模塊。
Glide已經(jīng)更新到4.9.0项秉,本文就不去介紹Glide v3中的自定義模塊绣溜,只介紹Glide v4中如何自定義模塊。當(dāng)然如果感興趣的話也可以學(xué)習(xí)一下舊版本中的自定義模塊娄蔼,推薦一篇非常優(yōu)秀的文章怖喻。
二、自定義模塊基本使用
Glide v4是使用注解機制來完成自定義模塊的創(chuàng)建工作的岁诉,因此在工作正式開始之前我們還需要引入一些必需的依賴庫锚沸。
1、添加對 Glide 的注解解析器的依賴和對OkHttp集成庫的依賴
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
implementation 'com.github.bumptech.glide:okhttp3-integration:4.8.0'
2涕癣、創(chuàng)建自定義模塊
從Glide v4開始哗蜈,Glide框架引入了注解機制,自定義模塊的創(chuàng)建也變得非常簡單。
- 首先要實現(xiàn)AppGlideModule 類恬叹。
- 接著給上述實現(xiàn)添加@GlideModule注解候生。
@GlideModule
public class MyAppGlideModule extends AppGlideModule {
@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
}
@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
}
}
- 最后,你應(yīng)該在你的 proguard.cfg 中 keep 住你的 AppGlideModule 實現(xiàn)绽昼。
-keep public class extends com.bumptech.glide.module.AppGlideModule
-keep class com.bumptech.glide.GeneratedAppGlideModuleImpl
這樣模塊類就創(chuàng)建完成了唯鸭。我們可以看到上述代碼中有兩個需要重寫的方法applyOptions和registerComponents,那么這兩個方法的作用是什么呢硅确?
applyOptions
認(rèn)真閱讀過上一篇文章的同學(xué)對applyOptions()
這個方法應(yīng)該比較熟悉了目溉,它在應(yīng)用程序選項一節(jié)中多次出現(xiàn)過,它的主要職責(zé)就是配置對大部分應(yīng)用程序合理的默認(rèn)選項菱农。
假如有這樣一個場景:我希望Glide在加載圖片的時候禁止任何緩存操作缭付。為了滿足這個條件,那么我應(yīng)用中的圖片加載語句可能是類似下面這樣的:
Glide.with(this)
.asDrawable()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.load(IMAGE_URL)
.into(imageView);
一直重復(fù)編寫這么長的語句顯然是不理智的循未,此時我們就可以在applyOptions方法中配置所有請求的默認(rèn)選項:
@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
RequestOptions requestOptions = new RequestOptions()
.skipMemoryCache(true) //不使用內(nèi)存緩存
.diskCacheStrategy(DiskCacheStrategy.NONE); //原圖和縮略圖都不進(jìn)行磁盤緩存
builder.setDefaultRequestOptions(requestOptions);
}
這樣所有的圖片加載請求在默認(rèn)情況下就不會進(jìn)行緩存操作了陷猫,我們的圖片加載語句也會變得很簡單:
Glide.with(this)
.load(IMAGE_URL)
.into(imageView);
registerComponents
registerComponents
,顧名思義的妖,這個方法的作用就是注冊組件绣檬,這也是這一篇文章要介紹的重點內(nèi)容。
假如有一天產(chǎn)品經(jīng)理提出了一個新功能嫂粟,需要顯示圖片的加載進(jìn)度娇未,由于Glide內(nèi)部是基于HttpUrlConnection實現(xiàn)網(wǎng)絡(luò)通訊的,我們在它的基礎(chǔ)之上無法實現(xiàn)監(jiān)聽下載進(jìn)度的功能星虹,因此我們就需要用OkHttp替換HttpUrlConnection零抬。
@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.addInterceptor(new ProgressInterceptor()); //攔截器
OkHttpClient okHttpClient = builder.build();
registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(okHttpClient));
}
這樣我們就成功地用OkHttp
替換掉HttpUrlConnection
來進(jìn)行網(wǎng)絡(luò)通訊。
在Registry
類中不僅定義了replace()
方法宽涌,還有prepend()
和append()
方法平夜,它們可以用于設(shè)置 Glide 嘗試每個ModelLoader
和ResourceDecoder
之間的順序,我們可以根據(jù)實際需求選用卸亮。
假如你的 ModelLoader
或者 ResourceDecoder
在某個地方失敗了褥芒,這時候你想將已有的數(shù)據(jù)交由 Glide 的默認(rèn)行為來處理,可以使用 prepend()
嫡良。 prepend()
將確保你的 ModelLoader
或 ResourceDecoder
先于之前注冊的其他組件并被首先執(zhí)行锰扶。如果你的 ModelLoader
或者 ResourceDecoder
從其 handles()
方法中返回了一個 false
或失敗,所有其他的 ModelLoader
或 ResourceDecoder
將以它們被注冊的順序執(zhí)行寝受,一次一個坷牛,作為一種回退方案。
要處理新的數(shù)據(jù)類型或提供一個到 Glide 默認(rèn)行為的回退很澄,使用 append()
京闰。append()
將確保你的 ModelLoader
或 ResourceDecoder
僅在 Glide 的默認(rèn)組件被嘗試后才會被調(diào)用颜及。 如果你正在嘗試處理 Glide 的默認(rèn)組件能處理的某些子類型 (例如一些特定的 Uri 授權(quán)或子類型),你可能需要使用 prepend()
來確保 Glide 的默認(rèn)組件不會在你的定制組件之前加載蹂楣。
要完全替換 Glide 的默認(rèn)行為并確保它絕不運行俏站,請使用 replace()
。 replace()
將移除所有處理給定模型和數(shù)據(jù)類的 ModelLoaders
痊土,并添加你的 ModelLoader
來代替肄扎。 replace()
在使用庫(例如 OkHttp 或 Volley)替換掉 Glide 的網(wǎng)絡(luò)邏輯時尤其有用,這種時候你會希望確保僅 OkHttp 或 Volley 被調(diào)用赁酝。