1、Glide的使用
Glide.with(this).load(url).into(imageView)
在當下Glide已經是很常見的圖片加載工具了,相信很多開發者都體會到其方便指出,Glide的使用就簡單一句話即可完成圖片的加載,但不要小看這句話,Glide的背後可是作出了成噸的工作,今天整理一下Glide的相關筆記,跟隨上面的一句代碼探索Glide的奇妙指出;
2、with()
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
- getRetriever(activity):獲取RequestManagerRetriever
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
return Glide.get(context).getRequestManagerRetriever();
}
從上面的代碼看出with()中直接調用一行代碼,這行代碼執行了getRetriever()和get()兩個方法,getRetriever()中獲取Glide的實例,然後獲取Glide配置中的RequestManagerRetriever對象,下面先看看Glide的初始化
2.1、Glide初始化
private static void initializeGlide(@NonNull Context context) {
initializeGlide(context, new GlideBuilder());
}
@SuppressWarnings("deprecation")
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
//(1)獲取@GlideModules註解生成的類
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
//(2)調用擴展GlideModule中的設置方法,加載初始化的配置,這裏可以在項目中自定義Glide的配置
annotationGeneratedModule.applyOptions(applicationContext, builder);
Glide glide = builder.build(applicationContext); //(3)執行build()實例化Glide
Glide.glide = glide; //(4)賦值單例提供的Glide
}
簡述上面的流程:
- 創建GlideBuilder實例,然後反射獲取程序中擴展的@GlideModule生成類,調用applyOptions()加載用戶自定義的配置,這裏的針對Glide的Generated API使用時的配置,關於Generated API的使用自行查閱文檔
- 使用GlideBuilder實例化Glide,並單例對外提供
2.2、GlideBuilder——配置並實例化Glide
Glide build(@NonNull Context context) {
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor(); //(1)實例化執行網絡資源加載線程池
}
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor(); //(2)實例化執行磁盤緩存的線程池
}
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor(); //(3)實例化動畫線程池
}
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build(); //(4)實例化計算內存緩存大小
}
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory(); //(5)
}
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
bitmapPool = new LruBitmapPool(size); //(6)初始化Bitmap池
} else {
bitmapPool = new BitmapPoolAdapter();
}
}
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes()); //(7)
}
if (memoryCache == null) {
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());//(8)初始化內存緩存
}
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context); //(9)實例化磁盤緩存工廠
}
if (engine == null) { //(10)將設置的信息初始化Engine
engine = new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
defaultRequestListeners = Collections.emptyList(); //(11)請求監聽器
RequestManagerRetriever requestManagerRetriever = new RequestManagerRetriever(requestManagerFactory); (12)
return new Glide( //(13)創建Glide
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled);
}
GlideBuilder初始化Gild時,完成了各種線程池和緩存的創建和配置,具體見代碼中的註釋這裏很多的配置對後面的分析很重要,最後創建的RequestManagerRetriever就是上面獲取的實例
- RequestManagerRetriever.get():根據傳入的Context不同分別調用不同的重載方法創建RequestManager
public RequestManager get(@NonNull Fragment fragment) {//get()多個重載方法
if (Util.isOnBackgroundThread()) { //(1)在後臺線程執行時,綁定Application生命週期
return get(activity.getApplicationContext());
} else {
FragmentManager fm = activity.getSupportFragmentManager(); //
return supportFragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());
}
}
public RequestManager get(@NonNull Activity activity) { //get()對Activity的重載
if (Util.isOnBackgroundThread()) {
。。。。。。
return fragmentGet( activity, fm,null, isActivityVisible(activity));
}
}
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) { //get()對Fragment的重載
if (Util.isOnBackgroundThread()) {
。。。。。。
return supportFragmentGet( activity, fm,null, isActivityVisible(activity));
}
}
public RequestManager get(@NonNull Context context) { //get()對Context的重載,判斷類型執行對應的重載方法
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
} else if (Util.isOnMainThread() && !(context instanceof Application)) {
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper) {
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context); //對於傳入Application Context的調用getApplicationManager()綁定Application週期
}
@NonNull
private RequestManager getApplicationManager(@NonNull Context context) {
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
Glide glide = Glide.get(context.getApplicationContext());
applicationManager =
factory.build(
glide,
new ApplicationLifecycle(),
new EmptyRequestManagerTreeNode(),
context.getApplicationContext());
}
}
}
return applicationManager;
}
//對於非Application,根據傳入的Activity/Fragment的包(app或v4)分別調用fragmentGet或supportFragmentGet,最終目的都在Activity/Fragment中添加隱藏的Fragment
@NonNull
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible) {
//(1)從傳入的fm中獲取添加的Fragment,如果爲null則創建並使用fm添加一個隱藏的Fragment,用於監聽生命週期的變化
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
Glide glide = Glide.get(context);
//(2)調用factory創建RequestManager,傳入ActivityFragmentLifecycle()監聽Fragment的生命週期,然後綁定RequestManager和Fragment
requestManager = factory.build( glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
總結:
- get()方法中主要是根據請求傳入的Context類型,執行不同邏輯用於確定請求的生命週期,這裏採用常見的添加隱形Fragment的方式監聽生命週期
- 傳入Application類型的Context調用get()綁定Application生命週期
- 傳入Activity/Fragment類型Context,若在非UI線程,則綁定Application週期,在UI線程爲Activity/Fragment添加隱形Fragment監聽生命週期
- 綁定生命週期實例化Glide後,調用factory創建RequestManager實例,這裏默認使用RequestManagerFactory
- RequestManagerFactory:Glide的默認工廠,實例化RequestManager保存請求的生命週期lifecycle,關於lifecycle如何控制生命週期在後面將會介紹;
requestManager = factory.build( glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
//(1)factory默認的是RequestManagerFactory
private static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() {
@NonNull
@Override
public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) {
return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);//(2)創建RequestManager
}
};
3、load()
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
public <ResourceType> RequestBuilder<ResourceType> as( @NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context); //創建RequestBuilder
}
- RequestBuilder.load():保存請求的數據(圖片地址)
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
@NonNull
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model; //保存請求的url
return this;
}
在with()中知道程序最終創建了RequestManager對象,RequestManager.load()方法中根據傳參類型創建對應的RequestBuilder並設置加載最終返回的數據類型,然後調用RequestBuilder.load(),此處傳入的數據類型將影響最終加載圖片的類型,因爲在加載完成後會根據此處設置的resourceClass進行響應的轉換;
4、into():加載圖片顯示到視圖中
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
switch (view.getScaleType()) { // (1)根據ImageView的scaleType設置RequestOptions
case CENTER_CROP:
requestOptions = requestOptions.clone().optionalCenterCrop();
break;
case CENTER_INSIDE:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
requestOptions = requestOptions.clone().optionalFitCenter();
break;
case FIT_XY:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
}
return into( // (2)執行into()
glideContext.buildImageViewTarget(view, transcodeClass),
null,
requestOptions,
Executors.mainThreadExecutor());
}
into()方法中代碼邏很簡潔:
-
根據設置ImageView條件配置響應的Options;
-
根據要加載的圖片類型,創建對應Target,此處的Target保存真正的ImageView並負責最終的圖片顯示
-
設置請求後的顯示線程爲主線程
-
調用into()執行圖片加載
-
GlideContext.buildImageViewTarget():根據請求的數據類型,調用ImageViewTargetFactory創建對應的Target,創建的Target封裝試圖View,這裏以請求的Drawable爲例,此處創建的是DrawableImageViewTarget
@NonNull
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
@NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodeClass); //此處的transcodeClass由上面知道傳遞的是Drawable.class
}
public class ImageViewTargetFactory {
@NonNull
@SuppressWarnings("unchecked")
public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
@NonNull Class<Z> clazz) {
if (Bitmap.class.equals(clazz)) {
return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view); //創建DrawableImageViewTarget
} else {
}
}
- into():構建最終的請求Request並執行請求
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
Request request = buildRequest(target, targetListener, options, callbackExecutor); //(1)構建Request
target.setRequest(request); //(2)調用ViewTarget保存Request
requestManager.track(target, request); //(3)執行Request請求
return target;
}
上面的代碼就做了兩件事,但這兩件事完成了整個的數據請求:
- 創建Request,此處最終創建的是SingleRequest
- 執行Request加載
4.1、創建SingleRequest實例
public static <R> SingleRequest<R> obtain(……){
SingleRequest<R> request = (SingleRequest<R>) POOL.acquire(); //(1)獲取或創建Request
if (request == null) {
request = new SingleRequest<>(); //創建Request
}
request.init( //調用Request.init()初始化請求信息和圖片加載信息
context,
glideContext,
model, //請求的地址
transcodeClass, //請求參數類型,此處爲String
requestOptions, //設置的options
overrideWidth, //設置的寬、高參數
overrideHeight,
priority,
target, //設置顯示的Target
targetListener, //設置監聽Target的加載
requestListeners, //設置請求監聽
requestCoordinator,
engine,
animationFactory, //加載動畫
callbackExecutor); //設置執行的線程池
}
4.2、執行Request,開始加載數據
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
requestTracker.runRequest(request); //執行請求的Target
}
- RequestTracker.runRequest():方法最終調用SingleRequest的方法
public void runRequest(@NonNull Request request) {
requests.add(request); //保存請求的Request
if (!isPaused) { //判斷Glide是否暫停
request.begin(); //直接進行請求
} else {
request.clear();
pendingRequests.add(request); //暫停時保存任務
}
}
runRequest中首先保存要執行的請求,然後判斷Glide的加載是否停止,初步猜測這裏的停止應該和生命週期有關,如果停止將請求Request加入到人去列表中,否則直接調用begin()執行Request
- SingleRequest.begin()
@Override
public synchronized void begin() {
status = Status.WAITING_FOR_SIZE; //設置標識位爲測量尺寸
if (Util.isValidDimensions(overrideWidth, overrideHeight)) { //如果已設置寬高尺寸,則直接調用 onSizeReady(),否則測量尺寸後再調用
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this); //測量後調用
}
if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
&& canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable()); //回調請求開始,顯示佔位Drawable
}
}
begin()方法執行3個過程:
- 如果已設置寬高尺寸,則直接調用 onSizeReady()
- 如果未設置則調用ImageView的測量方法,測量結束後回調onSizeReady()
- 回調target.onLoadStarted(getPlaceholderDrawable())表示加載開始顯示佔位圖
- SingleRequest.onSizeReady():繼續請求加載
public synchronized void onSizeReady(int width, int height) {
status = Status.RUNNING;
loadStatus = engine.load(
glideContext,
model, //請求參數
requestOptions.getSignature(), //請求的requestOptions
this.width, //請求寬、高
this.height,
requestOptions.getResourceClass(),
transcodeClass, //請求參數類型
priority,
requestOptions.getDiskCacheStrategy(), //請求設置的RequestOptions
requestOptions.getTransformations(),
requestOptions.isTransformationRequired(),
requestOptions.isScaleOnlyOrNoTransform(),
requestOptions.getOptions(),
requestOptions.isMemoryCacheable(),
requestOptions.getUseUnlimitedSourceGeneratorsPool(),
requestOptions.getUseAnimationPool(),
requestOptions.getOnlyRetrieveFromCache(),
this, // 此處傳遞的是ResourceCallback,SingleRequest實現了ResourceCallback接口
callbackExecutor); //執行線程池
}
onSizeReady中標記運行狀態,調用Engine.load()加載數據,傳入的參數也都是加載圖片基本配置和條件;
- Engine.load():執行加載數據
public synchronized <R> LoadStatus load() {
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations, //(1)創建緩存的Key
resourceClass, transcodeClass, options);
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable); //(2)從活躍的引用中加載緩存信息
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable); //(3)從緩存中獲取緩存實例
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache); //從緩存的Jobs列表中獲取EngineJob
if (current != null) {
current.addCallback(cb, callbackExecutor);
return new LoadStatus(cb, current);
}
EngineJob<R> engineJob = engineJobFactory.build( //對於新執行的任務,創建EngineJob
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
DecodeJob<R> decodeJob = decodeJobFactory.build( //創建執行解析任務的DecodeJob
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob); //在DecodeJob中添加DecodeJob.Callback實例,處理數據回調
jobs.put(key, engineJob); //保存執行的任務信息
engineJob.addCallback(cb, callbackExecutor); //將傳入的SingleRequest和執行的線程池對應添加到列表中
engineJob.start(decodeJob); //啓動執行任務
return new LoadStatus(cb, engineJob);
}
load()中執行的邏輯就明顯體現了Glide的緩存原理,詳細的執行會在緩存中介紹,這裏製作流程介紹,簡單總結:
- 首先根據加載的條件創建Glide 的緩存Key;
- 根據Key先從活躍的資源中獲取,獲取成功則返回,否則向下執行;
- 再從內存緩存中獲取,獲取成功則返回,否則向下執行;
- 對於都未獲取到的則創建DecodeJob和EngineJob加載並解析資源;
- EngineJob.start():獲取執行任務的線程池並執行任務
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor = decodeJob.willDecodeFromCache() //獲取執行的線程池
? diskCacheExecutor
: getActiveSourceExecutor();
executor.execute(decodeJob); //使用線程池執行任務,程序回到DecodeJob.run()
}
- DecodeJob.run():線程池執行加載的方法
@Override
public void run() {
runWrapped();
}
private void runWrapped() {
switch (runReason) {
case INITIALIZE:
stage = getNextStage(Stage.INITIALIZE); //根據緩存情況獲取下一步的執行條件
currentGenerator = getNextGenerator(); //獲取具體執行的DataFetcherGenerator實例
runGenerators(); //執行Generators
break;
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
}
}
private Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
return diskCacheStrategy.decodeCachedResource() //(1)判斷存在轉換後緩存文件則返回Stage標識,否則遞歸繼續判斷
? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
return diskCacheStrategy.decodeCachedData() //(2)判斷存在源數據緩存存在,則設置Stage標識,否則遞歸繼續判斷
? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
case DATA_CACHE: //(3)解析後文件和源文件緩存都不存在的情況:
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE; //如果設置只讀緩存則請求結束,否則獲取資源
}
}
//根據上一步設置的要執行的Stage的標識,獲取執行的DataFetcherGenerator實例
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
case RESOURCE_CACHE:
return new ResourceCacheGenerator(decodeHelper, this); //(1)從轉換資源緩存中獲取
case DATA_CACHE:
return new DataCacheGenerator(decodeHelper, this); //(2)從緩存的源文件中獲取
case SOURCE:
return new SourceGenerator(decodeHelper, this); //(3)沒有緩存資源,執行加載
}
}
//Glide巧妙的設置一次執行:獲取處理緩存資源 -> 獲取原始緩存資源 -> 網絡加載;只要一個環節加載成功,返回true則跳出循環
private void runGenerators() {
boolean isStarted = false;
while (!isCancelled && currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) { //調用startNext()執行加載,成功返回true,跳出循環
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
}
}
關於上面的代碼還是需要仔細思考下的,Glide使用getNextStage()和getNextGenerator()方法巧妙的實現了多種判斷,總結上面方法執行邏輯如下:
- getNextStage():根據當前狀態獲取下一步的操作類型,開始爲INITIALIZE狀態,此時判斷是否有轉換後的緩存,有則設置爲RESOURCE_CACHE,否則繼續回調判斷;此時傳入爲RESOURCE_CACHE狀態,判斷是否有原數據緩存,有設置DATA_CACHE,否則遞歸判斷,傳參爲DATA_CACHE;此時判斷是否設置制度緩存,如果設置但沒有緩存加載結束,未設置則設置SOURCE標識,表示要去加載資源;
- getNextGenerator():根據上一步設置的標識,創建對應的任務實例(讀取轉換後文件、源緩存文件、獲取網絡資源)
- runGenerators():執行任務,在執行結束後並設置標識
4.3、SourceGenerator
SourceGenerator(DecodeHelper<?> helper, FetcherReadyCallback cb) {
this.helper = helper;
this.cb = cb; //保存傳入的FetcherReadyCallback實例
}
@Override
public boolean startNext() {
while (!started && hasNextModelLoader()) {
loadData = helper.getLoadData().get(loadDataListIndex++); // loadData是在Glide初始化時註冊的
loadData.fetcher.loadData(helper.getPriority(), this); //獲取Fetcher,真正執行網絡請求的點地方,
}
}
return started;
}
方法執行runGenerators()會調用SourceGenerator.statNext()方法,statNext首先使用helper獲取loadData,此處的 helper是DecodeHelper實例,創建SourceGenerator時傳入的參數,方法回到DecodeJob中,在DecodeJobFactory創建DecodeJob時掉調用了DecodeJob.init(),init()方法中decodeHelper.init初始化decodeHelper
private final DecodeHelper<R> decodeHelper = new DecodeHelper<>();
DecodeJob<R> init(
……….) {
decodeHelper.init(
glideContext,
diskCacheProvider);
}
helper.getLoadData()獲取ModelLoader.LoadData()對象,Glide初始化時調用.append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())註冊的HttpGlideUrlLoader.Factory(),最終創建new LoadData<>(url, new HttpUrlFetcher(url, timeout)),後面加載的loadData.fetcher 其實調用的就是HttpUrlFetcher實例;
- HttpUrlFetcher :最終執行網絡請求,使用HttpUrlConnection執行圖片加載
@Override
public void loadData(@NonNull Priority priority,@NonNull DataCallback<? super InputStream> callback) {
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
}
//使用HttpUrl執行網絡請求
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,
Map<String, String> headers) throws IOException {
urlConnection = connectionFactory.build(url); //使用HttpUrlConnection執行網絡請求
for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
}
urlConnection.setConnectTimeout(timeout);
urlConnection.setReadTimeout(timeout);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
urlConnection.setInstanceFollowRedirects(false);
urlConnection.connect();
stream = urlConnection.getInputStream();
if (isCancelled) {
return null;
}
上面的邏輯很簡介直接請求網絡加載圖片,Glide的默認使用HttpUrl加載圖片,當然Glide也提供了配置Okhttp的方法;
5、請求成功回調
- HttpUrlFetcher執行網絡請求成功後,請求後回調的Callback,此處Callback是傳入的SourceGenerator
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
callback.onDataReady(result); //執行請求成功回調
} catch (IOException e) {
callback.onLoadFailed(e); //執行請求失敗回調
} finally {
}
- SourceGenerator.onDataReady()
@Override
public void onDataReady(Object data) {
DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) { //判斷是否緩存原始數據
dataToCache = data;
cb.reschedule(); // 緩存原始數據
} else { //處理獲取的數據
cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher, // 此處的cb創建時傳入的DecodeJob中創建的
loadData.fetcher.getDataSource(), originalKey);
}
}
如果Glide設置允許緩存源數據則執行數據緩存,否則執行DecodeJob.onDataFetcherReady進行轉換資源,此處cb其實是傳入的DecodeJob對象,所以方法回到進入DecodeJob;
- DecodeJob.onDataFetcherReady():執行數據轉換和解析
@Override
public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,DataSource dataSource, Key attemptedKey) {
decodeFromRetrievedData();
}
private void decodeFromRetrievedData() {
Resource<R> resource = null;
try { //(1)執行圖片的轉換
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
}
if (resource != null) {
notifyEncodeAndRelease(resource, currentDataSource); //(2) 通知加載結束並緩存數據
} else {
runGenerators();
}
}
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
Resource<R> result = resource;
notifyComplete(result, dataSource); // notifyCOmplete()調用callback.onResourceReady(resource, dataSource);
stage = Stage.ENCODE;
}
總結:
- 調用decodeFromData執行圖片的轉換
- 通知加載結束並緩存數據,此處回到callback爲EngineJob對象
- EngineJob.onResourceReady():執行加載資源回調
class EngineJob<R> implements DecodeJob.Callback<R>{
@Override
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
}
notifyCallbacksOfResult();
}
@Synthetic
void notifyCallbacksOfResult() {
synchronized (this) {
}
for (final ResourceCallbackAndExecutor entry : copy) {
entry.executor.execute(new CallResourceReady(entry.cb)); //調用線程池執行CallResourceReady
}
}
對上面最後執行代碼中的entey其實是ResourceCallbacksAndExecutors()的實例,內部封裝了List用於保存ResourceCallbackAndExecutor,代碼中使用for循環遍歷copy中的集合,那是什麼時候添加的呢?這裏代碼回到Engine.load()中有一行代碼(見下面),此時將cb保存到ResourceCallbackAndExecutor中,然而此處的cb就是SingleRequest中調用load()傳入的this,即cb就是SingleRequest
engineJob.addCallback(cb, callbackExecutor);
- CallResourceReady:對資源引用計數加一,回到將callCallbackOnResourceReady()將結果回傳給SingleRequest
@Override
public void run() {
engineResource.acquire();
callCallbackOnResourceReady(cb); //加載結束回調方法
}
}
synchronized void callCallbackOnResourceReady(ResourceCallback cb) {
try {
cb.onResourceReady(engineResource, dataSource);
}
}
- SingleRequest.onResourceReady()
public synchronized void onResourceReady(Resource<?> resource, DataSource dataSource) {
stateVerifier.throwIfRecycled();
loadStatus = null;
if (resource == null) {
onLoadFailed(exception); //加載失敗回調
return;
}
Object received = resource.get();
if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
onLoadFailed(exception);
return;
}
onResourceReady((Resource<R>) resource, (R) received, dataSource); //執行成功數據回調
}
private synchronized void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
try {
if (!anyListenerHandledUpdatingTarget) {
target.onResourceReady(result, animation); //執行Target,此處就是前面創建的DrawableImageViewTarget
}
} finally {
isCallingCallbacks = false;
}
}
看到最初創建請求的地方代表離成功不遠了,SingleRequest中根據加載的結果,回調Target中的方法,由前面的分析知道此時的Target是DrawableImageViewTarget實例
- DrawableImageViewTarget
@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
if (transition == null || !transition.transition(resource, this)) {
setResourceInternal(resource); //不執行顯示動畫
} else {
maybeUpdateAnimatable(resource); //執行顯示動畫
}
}
private void setResourceInternal(@Nullable Z resource) {
setResource(resource); //調用抽象方法,此方法在DrawableImageViewTarget中實現
maybeUpdateAnimatable(resource);
}
@Override
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource); //最終的顯示結果
}
- ImageViewTarget.onResourceReady()中根據設置的transtion確定是否執行動畫並分別處理
- 調用重寫的抽象方法,爲保存的ImageView設置圖片
Glide的源碼分析到此結束了,由於筆記很早之前就做了但一直沒整理成博客,這次的整理又整體看了遍源碼,即是複習也是學習,希望對想要了解的同學有所幫助;