glide替換okhttp以及更改連線超時時間(TIME_OUT)
Glide替換okhttp,更改超時時間,看似簡單,具體寫的過程中坑還是真多,特記錄一下,也幫助需要的人。本文基於Glide 4.x。
首先,替換okhttp,官方給了一個及其簡單的方式。
implementation "com.github.bumptech.glide:okhttp3-integration:4.6.1"
這個地方是有一個坑的。我實際做的時候,發現加上這一句以後,圖片死活載入不出來了 。以為替換的方式有問題,查了大量資料和原始碼都沒有結果。後來分析log發現log上寫連線失敗。我換了幾張網路圖片都不行,而用普通的連線方式是可以加載出圖片的。於是想到了是wifi代理證書問題。換了個wifi果然好了。。
OK,okhttp替換是很簡單(如果你的wifi沒有問題的話。。),下面來看定製TIME_OUT。去他引用的這個integration工程裡的OkHttpUrlLoader裡看,有internalClient這個OkHttpClinet,依舊是寫死的,不能定製其超時時間。OkHttpUrlLoader的Factory有兩個建構函式,自然就想到了能不能呼叫第二個建構函式,傳進一個定製了超時時間的OkHttpClient去。但是檢視這個Factory的呼叫樹,發現它是被OkHttpGlideModule(已經過時)和OkHttpLibraryGlideModule這兩個類呼叫的,這兩個類都是元件類,在Glide初始化的時候會執行registerComponents替換掉原來的GlideUrl。區別是一個是老的形式,必須在manifest裡定義meta-data,另一個是新的形式,用註解的方式替代manifest定義。
OkHttpGlideModule(已經過時)和OkHttpLibraryGlideModule這兩個類同時都生成了,應該是為了向下相容。然後我試著把斷點加到這兩個類的registerComponents方法中,發現只有OkHttpGlideModule這個類的方法執行了,而新的OkHttpLibraryGlideModule的方法並沒有執行。為什麼呢?於是只好debug Glide的原始碼。在Glide的initializeGlide方法中,有如下兩段程式碼:
List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList(); if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) { manifestModules = new ManifestParser(applicationContext).parse(); }
Set<Class<?>> excludedModuleClasses =
annotationGeneratedModule.getExcludedModuleClasses();
可以看到,分別去menifest裡和註解裡去找相應的GlideMode。其中getAnnotationGeneratedGlideModules是具體找註解類的過程。理論上先執行了manifest查詢替換,然後再執行的Annotation查詢替換,應該能執行OkHttpLibraryGlideModule裡的程式碼並且最後以它為準才對(因為他是後執行的,replace操作當然以後執行的為準)。但是為啥它沒有被執行到呢?
這個問題費了挺長時間,我自己定義了一個類似OkHttpLibraryGlideModule的註解GlideMode,也同樣執行不到。後來debug,發現出了異常GeneratedAppGlideModuleImpl找不到,不過異常的註釋終於給了我答案。。
"Failed to find GeneratedAppGlideModule. You should include an annotationProcessor compile dependency on com.github.bumptech.glide:compiler in your application and a @GlideModule annotated AppGlideModule implementation or LibraryGlideModules will be silently ignored"
最後一句,如果是implementation LibraryGlideModules則默默的忽略掉。。。坑啊,自動生成的OkHttpLibraryGlideModule是繼承的LibraryGlideModule,然後告訴我說如果繼承它則忽略掉。。好吧,我把我自己建立的MyOkHttpGlideModule繼承自AppGlideModule,然後client傳定製了timeOut的OkHttpClient,debug就一切正常了。
最後,MyOkHttpGlideModule原始碼如下:
public final class MyOkHttpGlideModule extends AppGlideModule {
OkHttpClient client=new OkHttpClient.Builder()
.connectTimeout(10000, TimeUnit.SECONDS)
.readTimeout(10000, TimeUnit.SECONDS)
.writeTimeout(10000, TimeUnit.SECONDS)
.build();
@Override
public void registerComponents(Context context, Glide glide ,Registry registry) {
OkHttpUrlLoader.Factory factory = new OkHttpUrlLoader.Factory(client);
registry.replace(GlideUrl.class, InputStream.class,factory);
}
}