最近新項目用了最新版本的Glide,發(fā)現(xiàn)語法結(jié)構(gòu)改變了不少,查看官方文檔 ,中文翻譯 ,記錄錄下。
選項(Options)
Glide v4 中的一個比較大的改動是Glide庫處理選項(centerCrop(),placeholder()等)的方式。在 v3 版本中,選項由一系列復(fù)雜的異構(gòu)建造者(multityped builders)單獨處理。在新版本中,由一個單一類型的唯一一個建造者接管一系列選項對象。Glide 的generated API進(jìn)一步簡化了這個操作:它會合并傳入建造者的選項對象和任何已包含的集成庫里的選項,以生成一個流暢的 API。
RequestBuilder
對于這類方法:
listener()thumbnail()load()into()
在 Glide v4 版本中,只存在一個RequestBuilder對應(yīng)一個你正在試圖加載的類型(Bitmap,Drawable,GifDrawable等)。RequestBuilder可以直接訪問對這個加載過程有影響的選項,包括你想加載的數(shù)據(jù)模型(url, uri等),可能存在的縮略圖請求,以及任何的監(jiān)聽器。RequestBuilder也是你使用into()或者preload()方法開始加載的地方:
RequestBuilderrequestBuilder=Glide.with(fragment).load(url);requestBuilder.thumbnail(Glide.with(fragment).load(thumbnailUrl)).listener(requestListener).load(url).into(imageView);
請求選項
對于這類方法:
centerCrop()placeholder()error()priority()diskCacheStrategy()
大部分選項被移動到了一個單獨的稱為RequestOptions的對象中,
RequestOptions options = new RequestOptions()
.centerCrop()
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.priority(Priority.HIGH);
RequestOptions允許你一次指定一系列的選項,然后對多個加載重用它們:
RequestOptionsmyOptions=newRequestOptions().fitCenter().override(100,100);Glide.with(fragment).load(url).apply(myOptions).into(drawableView);Glide.with(fragment).asBitmap().apply(myOptions).load(url).into(bitmapView);
變換
Glide v4 里的Transformations現(xiàn)在會替換之前設(shè)置的任何變換。在 Glide v4 中,如果你想應(yīng)用超過一個的Transformation,你需要使用transforms()方法:
Glide.with(fragment).load(url).apply(newRequestOptions().transforms(newCenterCrop(),newRoundedCorners(20))).into(target);
或使用generated API:
GlideApp.with(fragment).load(url).transforms(newCenterCrop(),newRoundedCorners(20)).into(target);
解碼格式
在 Glide v3, 默認(rèn)的DecodeFormat是DecodeFormat.PREFER_RGB_565,它將使用 [Bitmap.Config.RGB_565],除非圖片包含或可能包含透明像素。對于給定的圖片尺寸,RGB_565只使用 [Bitmap.Config.ARGB_8888] 一般的內(nèi)存,但對于特定的圖片有明顯的畫質(zhì)問題,包括條紋(banding)和著色(tinting)。為了避免RGB_565的畫質(zhì)問題,Glide 現(xiàn)在默認(rèn)使用ARGB_8888。結(jié)果是,圖片質(zhì)量變高了,但內(nèi)存使用也增加了。
要將 Glide v4 默認(rèn)的DecodeFormat改回DecodeFormat.PREFER_RGB_565,請在AppGlideModule中應(yīng)用一個RequestOption:
@GlideModulepublicfinalclassYourAppGlideModuleextendsGlideModule{@OverridepublicvoidapplyOptions(Contextcontext,GlideBuilderbuilder){builder.setDefaultRequestOptions(newRequestOptions().format(DecodeFormat.PREFER_RGB_565));}}
關(guān)于使用AppGlideModules的更多信息,請查閱配置頁面。請注意,為了讓 Glide 發(fā)現(xiàn)你的AppGlideModule實現(xiàn),你必須確保添加了對 Glide 的注解解析器的依賴。關(guān)于如何設(shè)置這個庫的更多信息,請查看下載和設(shè)置。
過渡選項
對于這類方法:
crossFade()animate()
控制從占位符到圖片和/或縮略圖到全圖的變換的選項,被移動到了TransitionOptions中。
要應(yīng)用過渡(之前的動畫),請使用下列選項中符合你請求的資源類型的一個:
如果你想移除任何默認(rèn)的過渡,可以使用TransitionOptions.dontTransition()]17。
過渡動畫通過RequestBuilder應(yīng)用到請求上:
Glide.with(fragment).load(url).transition(withCrossFade(R.anim.fade_in,300));
默認(rèn)過渡
不同于 Glide v3,Glide v4 將不會默認(rèn)應(yīng)用交叉淡入或任何其他的過渡效果。每個請求必須手動應(yīng)用過渡。
Generated API
為了讓使用 Glide v4 更簡單輕松,Glide 現(xiàn)在也提供了一套可以為應(yīng)用定制化生成的 API。應(yīng)用可以通過包含一個標(biāo)記了 [AppGlideModule][2的實現(xiàn)來訪問生成的 API。如果你不了解這是怎么工作的,可以查看Generated API。
Generated API添加了一個GlideApp類,該類提供了對RequestBuilder和RequestOptions子類的訪問。RequestOptions的子類包含了所有RequestOptions中的方法,以及GlideExtensions中定義的方法。RequestBuilder的子類則提供了生成的RequestOptions中所有方法的訪問,而不需要你再手動調(diào)用apply。舉個例子:
在沒有使用 Generated API 時,請求大概長這樣:
Glide.with(fragment).load(url).apply(centerCropTransform().placeholder(R.drawable.placeholder).error(R.drawable.error).priority(Priority.HIGH)).into(imageView);
使用 Generated API,RequestOptions的調(diào)用可以被內(nèi)聯(lián):
GlideApp.with(fragment).load(url).centerCrop().placeholder(R.drawable.placeholder).error(R.drawable.error).priority(Priority.HIGH).into(imageView);
你仍然可以使用生成的RequestOptions子類來應(yīng)用相同的選項到多次加載中;但生成的RequestBuilder子類可能在多數(shù)情況下更為方便。
類型(Type)與目標(biāo)(Target)
選擇資源類型
Glide 允許你指定你想加載的資源類型。如果你指定了一個超類型,Glide 會嘗試加載任何可用的子類型。比如,如果你請求的是 Drawable ,Glide 可能會加載一個 BitmapDrawable 或一個 GifDrawable 。而如果你請求的是一個 GifDrawable ,要么會加載出一個 GifDrawable,要么報錯–只要圖片不是 GIF 的話(即使它湊巧是一個完全有效的圖片也是如此)。
默認(rèn)請求的類型是 Drawable:
Glide.with(fragment).load(url)
如果要明確指定請求 Bitmap:
Glide.with(fragment).asBitmap()
如果要創(chuàng)建一個文件路徑(本地圖片的最佳選項):
Glide.with(fragment).asFile()
如果要下載一個遠(yuǎn)程文件到緩存然后創(chuàng)建文件路徑:
Glide.with(fragment).downloadOnly()// or if you have the url already:Glide.with(fragment).download(url);
Drawables
Glide v3 版本中的GlideDrawable類已經(jīng)被移除,支持標(biāo)準(zhǔn)的AndroidDrawable。GlideBitmapDrawable也已經(jīng)被刪除,由BitmapDrawable代替之。
如果你想知道某個 Drawable 是否是動畫(animated),可以檢查它是否為Animatable的實例。
booleanisAnimated=drawableinstanceofAnimatable;
Targets
onResourceReady方法的簽名做了一些修改。例如,對于Drawables:
onResourceReady(GlideDrawabledrawable,GlideAnimationanim)
現(xiàn)在改為:
onResourceReady(Drawabledrawable,Transitiontransition);
類似地,onLoadFailed的簽名也有一些變動:
onLoadFailed(Exceptione,DrawableerrorDrawable)
改為:
onLoadFailed(DrawableerrorDrawable)
如果你想要獲得更多導(dǎo)致加載失敗的錯誤信息,你可以使用RequestListener。
取消請求
Glide.clear(Target)方法被移動到了RequestManager中:
Glide.with(fragment).clear(target)
使用RequestManager清除之前由它啟動的加載過程,通常能提高性能,雖然這并不是強制要求的。Glide v4 會為每一個 Activity 和 Fragment 跟蹤請求,所以你需要在合適的層級去清除請求。
配置
在 Glide v3 中,配置使用一個或多個GlideModule來完成。而在 Glide v4 中,配置改為使用一個類似但稍微復(fù)雜的系統(tǒng)來完成。
關(guān)于這個新系統(tǒng)的細(xì)節(jié),可以查看配置頁面。
應(yīng)用程序
在早期版本中使用了一個GlideModule的應(yīng)用,可以將它轉(zhuǎn)換為一個AppGlideModule。
在 Glide v3 中,你可能會有一個像這樣的GlideModule:
publicclassGiphyGlideModuleimplementsGlideModule{@OverridepublicvoidapplyOptions(Contextcontext,GlideBuilderbuilder){builder.setMemoryCache(newLruResourceCache(10*1024*1024));}@OverridepublicvoidregisterComponents(Contextcontext,Registryregistry){registry.append(Api.GifResult.class,InputStream.class,newGiphyModelLoader.Factory());}}
在 Glide v4 中,你需要將其轉(zhuǎn)換成一個AppGlideModule,它看起來像這樣:
@GlideModulepublicclassGiphyGlideModuleextendsAppGlideModule{@OverridepublicvoidapplyOptions(Contextcontext,GlideBuilderbuilder){builder.setMemoryCache(newLruResourceCache(10*1024*1024));}@OverridepublicvoidregisterComponents(Contextcontext,Registryregistry){registry.append(Api.GifResult.class,InputStream.class,newGiphyModelLoader.Factory());}}
請注意,@GlideModule注解不能省略。
如果你的應(yīng)用擁有多個GlideModule,你需要把其中一個轉(zhuǎn)換成AppGlideModule,剩下的轉(zhuǎn)換成LibraryGlideModule。除非存在AppGlideModule,否則程序不會發(fā)現(xiàn)LibraryGlideModule,因此您不能僅使用LibraryGlideModule。
程序庫
擁有一個或多個GlideModule的程序庫應(yīng)該使用LibraryGlideModule。程序庫不應(yīng)該使用AppGlideModule,因為它在一個應(yīng)用里只能有一個。因此,如果你試圖在程序庫里使用它,將不僅會妨礙這個庫的用戶設(shè)置自己的選項,還會在多個程序庫都這么做時造成沖突。
例如,v3 版本中 Volley 集成庫的GlideModule:
publicclassVolleyGlideModuleimplementsGlideModule{@OverridepublicvoidapplyOptions(Contextcontext,GlideBuilderbuilder){// Do nothing.}@OverridepublicvoidregisterComponents(Contextcontext,Registryregistry){registry.replace(GlideUrl.class,InputStream.class,newVolleyUrlLoader.Factory(context));}}
在 v4 版本中可以轉(zhuǎn)換成為一個LibraryGlideModule:
@GlideModulepublicclassVolleyLibraryGlideModuleextendsLibraryGlideModule{@OverridepublicvoidregisterComponents(Contextcontext,Registryregistry){registry.replace(GlideUrl.class,InputStream.class,newVolleyUrlLoader.Factory(context));}}
清單解析
為了簡化遷移過程,盡管清單解析和舊的GlideModule接口已被廢棄,但它們在 v4 版本中仍被支持。AppGlideModule,LibraryGlideModule,與已廢棄的GlideModule可以在一個應(yīng)用中共存。
然而,為了避免檢查元數(shù)據(jù)的性能天花板(以及相關(guān)的 bugs ),你可以在遷移完成后禁用掉清單解析,在你的AppGlideModule中復(fù)寫一個方法:
@GlideModulepublicclassGiphyGlideModuleextendsAppGlideModule{@OverridepublicbooleanisManifestParsingEnabled(){returnfalse;}...}
using(), ModelLoader, StreamModelLoader.
ModelLoader
ModelLoaderAPI 在 v4 版本中仍然存在,并且它的設(shè)計目標(biāo)仍然和它在 v3 中一樣,但有一些細(xì)節(jié)變化。
第一個細(xì)節(jié),ModelLoader的子類型如StreamModelLoader,現(xiàn)在已沒有存在的必要,用戶可以直接實現(xiàn)ModelLoader。例如,一個StreamModelLoader類現(xiàn)在可以通過ModelLoader的方式來實現(xiàn)和引用。
第二,ModelLoader現(xiàn)在并不直接返回DataFetcher,而是返回LoadData。[LoadData] 是一個非常簡單的封裝,包含一個磁盤緩存鍵和一個DataFetcher。
第三,ModelLoaders有一個handles()方法,這使你可以為同一個類型參數(shù)注冊超過一個的 ModelLoader 。
將一個ModelLoader從 v3 API轉(zhuǎn)換到 v4 API ,通常是很簡單直接的。如果你在你的 v3ModelLoader中只是簡單滴返回一個DataFetcher:
publicfinalclassMyModelLoaderimplementsStreamModelLoader{@OverridepublicDataFetchergetResourceFetcher(Filemodel,intwidth,intheight){returnnewMyDataFetcher(model);}}
那么你在 v4 替代類上需要做的僅僅只是封裝一下這個 data fetcher :
publicfinalclassMyModelLoaderimplementsModelLoader{@OverridepublicLoadDatabuildLoadData(Filemodel,intwidth,intheight,Optionsoptions){returnnewLoadData<>(model,newMyDataFetcher(model));}@Overridepublicvoidhandles(Filemodel){returntrue;}}
請注意,除了DataFetcher之外,模型也被傳遞給LoadData作為緩存鍵的一部分。這個規(guī)則為某些特殊場景提供了更多對磁盤緩存鍵的控制。大部分實現(xiàn)可以直接將 model 傳入LoadData,就像上面這樣。
如果你僅僅是想為某些 model(而不是所有)使用你的 ModelLoader,你可以在你嘗試加載 model 之前使用handles()方法來檢查它。如果你從handles方法中返回了false,那么你的ModelLoader將不能加載指定的 model ,即使你的ModelLoader類型 (在這個例子里是File和InputStream) 與之匹配。
舉個例子,如果你在某個指定文件夾下寫入了加密的圖片,你可以使用handles方法來實現(xiàn)一個ModelLoader以從那個特定的文件夾下解密圖片,但是并不用于加載其他文件夾下的File:
publicfinalclassMyModelLoaderimplementsModelLoader{privatestaticfinalStringENCRYPTED_PATH="/my/encrypted/folder";@OverridepublicLoadDatabuildLoadData(Filemodel,intwidth,intheight,Optionsoptions){returnnewLoadData<>(model,newMyDataFetcher(model));}@Overridepublicvoidhandles(Filemodel){returnmodel.getAbsolutePath().startsWith(ENCRYPTED_PATH);}}
using()
usingAPI在 Glide v4 中被刪除了,這是為了鼓勵用戶使用AppGlideModule一次性地注冊所有組件,避免對象重用(re-use, 原文如此 –譯者注)。你無需每次加載圖片時都創(chuàng)建一個新的ModelLoader;你應(yīng)該在AppGlideModule中注冊一次,然后交給 Glide 在每次加載時檢查 model (即你傳入load()方法的對象)來決定什么時候使用你注冊的 ``ModelLoader` 。
為了確保你僅為特定的 model 使用你的ModelLoader,請像上面展示的那樣實現(xiàn)handles方法:檢查每個 model ,但僅在應(yīng)當(dāng)使用你的ModelLoader時才返回 true 。