國(guó)外html5特效網(wǎng)站深圳seo秘籍
基于上一篇介紹了Glide的使用篇本文分析一下Glide的源碼實(shí)現(xiàn),看看我們簡(jiǎn)單幾步就實(shí)現(xiàn)的圖片展示功能在源碼中是怎樣完成的。
一、Glide中的核心文件
先逐個(gè)介紹一下個(gè)人以為的幾個(gè)核心類:?
1、Glide
Glide是必經(jīng)的入口,通過(guò)Glide.get(context)主要是做初始化,包括、Registry、RequestManagerRetriever等核心組件。
2、RequestManagerRetriever
獲取RequestManager,創(chuàng)建無(wú)UI的RequestManagerFragment綁定生命周期監(jiān)聽(tīng),通過(guò)Lifecycle監(jiān)聽(tīng)宿主生命周期。
3、GlideBuilder?
GlideBuilder?它的build方法會(huì)配置線程池、緩存策略等、初始化Engine以及初始化Glide對(duì)象。
4、RequestBuilder
構(gòu)建請(qǐng)求參數(shù),asDrawable、asGif、asBitmap加載不同類型,默認(rèn)asDrawable。最終由Engine調(diào)度三級(jí)緩存(活動(dòng)資源/LRU內(nèi)存/磁盤(pán))。
5、?RequestManager?
管理請(qǐng)求隊(duì)列,協(xié)調(diào)生命周期。
6、RequestManagerFragment
?綁定生命周期?非Application上下文:創(chuàng)建無(wú)UI的RequestManagerFragment,通過(guò)Lifecycle監(jiān)聽(tīng)宿主生命周期。主線程調(diào)用時(shí)通過(guò)FragmentManager管理Fragment,子線程使用Application級(jí)生命周期。
7、LifecycleListener
定義生命周期的接口,里面onStart、onStop、onDestroy三個(gè)方法與宿主Fragment或Activity的同名生命周期綁定。
8、Engine
合理調(diào)度三級(jí)緩存(調(diào)取活動(dòng)資源/內(nèi)存/磁盤(pán))
9、Target?
Target是一個(gè)接口,繼承自LifecycleListener并且額外增加了一些加載過(guò)程中的方法,比如onLoadStarted、onLoadFailed、onLoadCleared等等。他還有一個(gè)抽象的實(shí)現(xiàn)類BaseTarget。
后面子子孫孫還有很多抽象類繼承BaseTarget,比如下一代ViewTarget、下下代ImageViewTarget
、下下下代是BitmapImageViewTarget和DrawableImageViewTarget以及ThumbnailImageViewTarget,他們才是into方法傳入的實(shí)際展示圖片的控件。
是借助ImageViewTargetFactory來(lái)創(chuàng)建對(duì)應(yīng)Target(如BitmapImageViewTarget)。
10、DecodeJob?
看得出來(lái)他是做解碼工作的,緩存未命中時(shí)創(chuàng)建DecodeJob,提交到EngineJob線程池。實(shí)現(xiàn)了Runnable接口因此再run方法中借助DataFetcher進(jìn)行解碼。
11、DataFetcher
上面提到了借助DataFetcher進(jìn)行解碼,但他是個(gè)接口,所以真正工作是它的實(shí)現(xiàn)類們,比如FileFetcher、AssetPathFetcher和HttpUrlFetcher等都不同地址來(lái)源的圖片進(jìn)行解碼。
12、Registry
組件注冊(cè)中心,支持?jǐn)U展ModelLoader等模塊。根據(jù)模型類型(如String/File)匹配對(duì)應(yīng)的ModelLoader。
二、分階段梳理工作流程
1、注
Glide.with(mActivity).load(R.drawable.czzs_step_station).into(image);
以在Activity中加載為例,這也是使用最多的場(chǎng)景。其他場(chǎng)景請(qǐng)按此思路自行梳理。
2、初始化階段?:
Glide.with()通過(guò)RequestManagerRetriever獲取RequestManager,綁定生命周期監(jiān)聽(tīng)。
2.1 獲取RequestManager
public static RequestManager with(Activity activity) {return getRetriever(activity).get(activity);
}
2.2 獲取RequestManagerRetriever
private static RequestManagerRetriever getRetriever(@Nullable Context context) {// Context could be null for other reasons (ie the user passes in null), but in practice it will// only occur due to errors with the Fragment lifecycle.Preconditions.checkNotNull(context,"You cannot start a load on a not yet attached View or a Fragment where getActivity() "+ "returns null (which usually occurs when getActivity() is called before the Fragment "+ "is attached or after the Fragment is destroyed).");return Glide.get(context).getRequestManagerRetriever();
}
順著捋會(huì)找到Glide中的initializeGlide方法,此處代碼角度,只貼出實(shí)例化GlideBuilder以及通過(guò)它的build方法創(chuàng)建Glide對(duì)象,并將Glide對(duì)象聲明為成員變量。
GlideBuilder builder = new GlideBuilder().setRequestManagerFactory(factory);
for (GlideModule module : manifestModules) {module.applyOptions(applicationContext, builder);
}
if (annotationGeneratedModule != null) {annotationGeneratedModule.applyOptions(applicationContext, builder);
}
Glide glide = builder.build(applicationContext);
for (GlideModule module : manifestModules) {module.registerComponents(applicationContext, glide, glide.registry);
}
if (annotationGeneratedModule != null) {annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
Glide.glide = glide;
然后上面的builder.build(applicationContext);中初始化了Engine、RequestManagerRetriever
以及Glid,當(dāng)然也創(chuàng)建了線程池,只關(guān)鍵部分代碼:
if (engine == null) {engine = new Engine(memoryCache, diskCacheFactory, diskCacheExecutor, sourceExecutor,GlideExecutor.newUnlimitedSourceExecutor());}RequestManagerRetriever requestManagerRetriever = new RequestManagerRetriever(requestManagerFactory);return new Glide(context,engine,memoryCache,bitmapPool,arrayPool,requestManagerRetriever,connectivityMonitorFactory,logLevel,defaultRequestOptions.lock());
}
2.3 綁定生命周期
現(xiàn)在看2.1中后半部分get(activity),這里是調(diào)用RequestManagerRetriever的get方法:
public RequestManager get(Activity activity) {if (Util.isOnBackgroundThread()) {return get(activity.getApplicationContext());} else {assertNotDestroyed(activity);android.app.FragmentManager fm = activity.getFragmentManager();return fragmentGet(activity, fm, null /*parentHint*/);}
}
這里出現(xiàn)了FragmentManager,它就是要創(chuàng)建無(wú)UI的RequestManagerFragment,通過(guò)Lifecycle監(jiān)聽(tīng)宿主生命周期。?創(chuàng)建fragment的代碼:
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm, android.app.Fragment parentHint) {RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);if (current == null) {current = pendingRequestManagerFragments.get(fm);if (current == null) {current = new RequestManagerFragment();current.setParentFragmentHint(parentHint);pendingRequestManagerFragments.put(fm, current);fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();}}return current;
}
現(xiàn)在準(zhǔn)備工作基本完成了。
2、?加載階段?:
load(R.drawable.czzs_step_station).into(image);
傳入圖片路徑和ImageView組件。
public RequestBuilder<Drawable> load(@Nullable Object model) {return asDrawable().load(model);
}
RequestBuilder構(gòu)建請(qǐng)求參數(shù),最終由Engine調(diào)度三級(jí)緩存(活動(dòng)資源/LRU內(nèi)存/磁盤(pán))。
public Target<TranscodeType> into(ImageView view) {省略很多行。。。return into(context.buildImageViewTarget(view, transcodeClass));
}
buildImageViewTarget方法創(chuàng)建一個(gè)Target實(shí)例,其實(shí)就是上面提到的BitmapImageViewTarget或DrawableImageViewTarget。
@SuppressWarnings("unchecked")
public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) {if (Bitmap.class.equals(clazz)) {return (Target<Z>) new BitmapImageViewTarget(view);} else if (Drawable.class.isAssignableFrom(clazz)) {return (Target<Z>) new DrawableImageViewTarget(view);} else {throw new IllegalArgumentException("Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");}
}
然后進(jìn)入RequestManager的track方法:
void track(Target<?> target, Request request) {targetTracker.track(target);requestTracker.runRequest(request);
}
下一步
public void runRequest(Request request) {requests.add(request);if (!isPaused) {request.begin();} else {pendingRequests.add(request);}
}
進(jìn)入Request的實(shí)現(xiàn)類SingleRequest中的begin方法開(kāi)始處理加載。
3、?解碼階段?:
解碼是用DataFetcher和它的子實(shí)現(xiàn)類們:
這是加載結(jié)果的兩個(gè)回調(diào):
這里說(shuō)一下Glide是怎樣加載網(wǎng)絡(luò)圖片的,沒(méi)錯(cuò),和其他網(wǎng)絡(luò)請(qǐng)求一樣她也是用的HttpURLConnection。
在它的實(shí)現(xiàn)類HttpUrlFetcher中loadData方法:
@Override
public void loadData(Priority priority, DataCallback<? super InputStream> callback) {long startTime = LogTime.getLogTime();final InputStream result;try {result = loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/,glideUrl.getHeaders());} catch (IOException e) {if (Log.isLoggable(TAG, Log.DEBUG)) {Log.d(TAG, "Failed to load data for url", e);}callback.onLoadFailed(e);return;}if (Log.isLoggable(TAG, Log.VERBOSE)) {Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime)+ " ms and loaded " + result);}callback.onDataReady(result);
}
這里會(huì)將結(jié)果callback.onDataReady(result);毀掉了上面截圖中提到的onDataReady方法。
調(diào)用loadDataWithRedirects方法里:
這里如果失敗還會(huì)重新請(qǐng)求連接,最多重連五次:
private static final int MAXIMUM_REDIRECTS = 5;
最后各種通過(guò)FetcherReadyCallback以及其他各種回調(diào),最終在BitmapImageViewTarget展示圖片內(nèi)容:
/*** Sets the {@link android.graphics.Bitmap} on the view using {@link* android.widget.ImageView#setImageBitmap(android.graphics.Bitmap)}.** @param resource The bitmap to display.*/
@Override
protected void setResource(Bitmap resource) {view.setImageBitmap(resource);
}
三、其實(shí)還有一些其他很重要的公共類:
有一個(gè)線程池:
還一個(gè)上下文:
一個(gè)異常類:
Glide是一個(gè)非常優(yōu)秀的框架,源碼架構(gòu)設(shè)計(jì)的太好了。另外想了解Glide使用的朋友可以參考上一篇《展開(kāi)說(shuō)說(shuō)Android之Glide詳解_使用篇》。
個(gè)人總結(jié)記錄,才疏學(xué)淺,如有錯(cuò)誤,歡迎指正,多謝。?