Glide圖片下載架構完全解析


本文將分析圖片處理框架Glide的加載流程,同時也會對緩存,網絡請求,自定義模塊做相應分析,文中代碼使用的是目前(2020.3)最新的版本4.11.0。

Glide框架總覽

Glide是一個非常複雜的框架,下面我們根據各模塊的作用做出如下劃分:
Glide主要模塊

圖片加載源碼分析

Glide最基本的使用流程就是下面這行代碼,其它所有擴展的額外功能都是以其建造者鏈式調用的基礎上增加的。

GlideApp.with(context).load(url).into(imageView);

下面我們將對該用法進行深入的源碼分析。

Glide.with()

Glide爲我們提供多個Glide.with()實現,我們主要圍繞with(Context context) 展開分析
with方法

1. Glide.with(Context)
return getRetriever(activity).get(activity)
@Glide.java
RequestManagerRetriever getRetriever(context) {
	...
	return Glide.get(context).getRequestManagerRetriever();
}
//使用雙檢鎖方式實現單例
public static Glide get(@NonNull Context context) {
	if (glide == null) {
	 //獲取用戶自定義GlideModule
	  GeneratedAppGlideModule annotationGeneratedModule =getAnnotationGeneratedGlideModules(context.getApplicationContext());
	  synchronized (Glide.class) {
		if (glide == null) {
		  checkAndInitializeGlide(context, annotationGeneratedModule);
		}
	  }
	}
	return glide;
}
void checkAndInitializeGlide(context, generatedAppGlideModule) {
	...
	initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
	...
}
void initializeGlide(context, builder, annotationGeneratedModule) {
	...
	//1.1 獲取manifest中GlideModule模塊
	if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
      manifestModules = new ManifestParser(applicationContext).parse();
    }
	...
	//將自定義GlideModule信息(factory)添加到GlideBuilder中
	RequestManagerRetriever.RequestManagerFactory factory =
        annotationGeneratedModule != null
            ? annotationGeneratedModule.getRequestManagerFactory : null;
    builder.setRequestManagerFactory(factory);
    //1.2將GlideBuilder通過applyOptions添加到GlideModule中
    for (com.bumptech.glide.module.GlideModule module : manifestModules) {
      module.applyOptions(applicationContext, builder);
    }
    if (annotationGeneratedModule != null) {
      annotationGeneratedModule.applyOptions(applicationContext, builder);
    }
	//--> 2.創建Glide實例
	Glide glide = builder.build(applicationContext);
	...
	//1.3 registerComponents:用於註冊編解碼器,ModelLoader等,具體可以參考@Resistry中的方法
	if (annotationGeneratedModule != null) {
      annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
    }
    applicationContext.registerComponentCallbacks(glide);
    Glide.glide = glide;
}

這裏使用雙檢鎖模式來獲取Glide對象的單例,在1.1中,如果沒有帶註解的GlideModule,或者該GlideModule中isManifestParsingEnabled()爲true,則調用ManifestParser解析AndroidManifest.xml中以獲取值爲“GlideModule”的meta-data配置,並將相應的自定義模塊實例化。由於可以實例化多個GlideModule,因此得到的是一個GlideModule的List集合。
在1.2中,將builder通過applyOptions方法加入到module中,在自定義module中我們通過重寫applyOptions方法可以對module進行定製。
在1.3中,提供registerComponents來修改glide中組件,用於註冊編解碼器,ModelLoader等,比如替換網絡請求成OkHttp的方法, 就是通過該函數註冊

2. GlideBuilder.build

GlideBuilder 是用來創建 Glide 實例的類,具體實現如下:

@NonNull
  Glide build(@NonNull Context context) {
    if (sourceExecutor == null) { //創建圖片線程池
      sourceExecutor = GlideExecutor.newSourceExecutor();
    }
    if (diskCacheExecutor == null) { //創建硬盤緩存線程池
      diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
    }
    if (animationExecutor == null) { //創建動畫線程池
      animationExecutor = GlideExecutor.newAnimationExecutor();
    }
    //TODO:默認4M,如果是低內存設備爲2M,後文[緩存機制]會有詳細分析
    if (memorySizeCalculator == null) { 
      memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
    }
    if (connectivityMonitorFactory == null) {
      connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
    }
    if (bitmapPool == null) {
      int size = memorySizeCalculator.getBitmapPoolSize();
      if (size > 0) {
        bitmapPool = new LruBitmapPool(size);
      } else {
        bitmapPool = new BitmapPoolAdapter();
      }
    }
    if (arrayPool == null) {
      arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
    }
    if (memoryCache == null) {  // 創建內存緩存
      memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
    }
    if (diskCacheFactory == null) {
      diskCacheFactory = new InternalCacheDiskCacheFactory(context);
    }
	// 創建任務和資源管理引擎(線程池,內存緩存和硬盤緩存對象)
    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              animationExecutor,
              isActiveResourceRetentionAllowed);
    }
    if (defaultRequestListeners == null) {
      defaultRequestListeners = Collections.emptyList();
    } else {
      defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
    }
    //創建requestManagerRetriever,用於創建requestManager
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);
    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptionsFactory,
        defaultTransitionOptions,
        defaultRequestListeners,
        isLoggingRequestOriginsEnabled,
        isImageDecoderEnabledForBitmaps);
  }

這個方法中會創建BitmapPool、MemoryCache、DiskCache等對象的實例,並在最後一句創建一個Glide對象的實例,然後將前面創建的這些實例傳入到Glide對象當中,以供後續的圖片加載操作使用。
同時,我們注意到,build 中創建任何對象都有一個判空的檢查,只有對象爲空纔會去創建其實例,也就是說,我們可以applyOptions方法對這些配置對象提前初始化,進而實現更改Glide配置的功能。
具體如何自定義模塊,可以參考郭神的文章:《Android圖片加載框架最全解析(六),探究Glide的自定義模塊功能》,文中涉及如何替換網絡組件,如何替換緩存模塊等非常棒的操作。

3. Glide構造方法

將任務管理對象(registry)、array緩存、管理引擎等傳入glideContext

 Glide(...) {
	...
	//登記任務管理對象,根據任務類型,分發給相應任務進行處理
    registry = new Registry();
    ...
	//註冊編解碼器,ModelLoader等組件
    registry
        .append(ByteBuffer.class, new ByteBufferEncoder())
        .append(InputStream.class, new StreamEncoder(arrayPool))
     ...
	 //Target工廠: 根據子類生產對應類型taget,
	 //包括BitmapImageViewTarget和DrawableImageViewTarget
    ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
    glideContext =
        new GlideContext(
            context,
            arrayPool,
            registry,
            imageViewTargetFactory,
            defaultRequestOptionsFactory,
            defaultTransitionOptions,
            defaultRequestListeners,
            engine,
            isLoggingRequestOriginsEnabled,
            logLevel);
  }
4. RequestManagerRetriever.get
  public RequestManager get(@NonNull Context context) {
    if (context == null) {
      throw new IllegalArgumentException("You cannot start a load on a null Context");
    } else if (Util.isOnMainThread() && !(context instanceof Application)) {
	  //如果非ApplicationContext, 將請求的生命週期同對於的Fragment/Activity綁定
      if (context instanceof FragmentActivity) {
        return get((FragmentActivity) context);
      } else if (context instanceof Activity) {
        return get((Activity) context);
      } else if (context instanceof ContextWrapper
          && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
        return get(((ContextWrapper) context).getBaseContext());
      }
    }
	//如果是ApplicationContext或者子線程,和Application生命週期綁定
    return getApplicationManager(context);
  }
  @NonNull
  private RequestManager supportFragmentGet(...) {
    //創建一個不可見的Fragment,用於檢測Activity生命週期
    SupportRequestManagerFragment current =
        getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) { //確保一個Activity對於一個requestManager
      Glide glide = Glide.get(context);
      //創建requestManger,將Glide和Activity生命週期綁定
      //參考[5.requestManager生命週期]
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), 
          current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

通過RequestManagerRetriever.get創建RequestManager,詳細邏輯如下:

  1. 如果 with 方法的參數爲 Activity 或者 Fragment ,則最終調用 RequestManagerRetriever 中的 fragmentGet(Context, android.app.FragmentManager) 方法創建 RequestManager
  2. 如果 with 方法的參數爲 android.support.v4.app.Fragment 或者android.support.v4.app.FragmentActivity,則最終調用 supportFragmentGet(Context, android.support.v4.app.FragmentManager) 方法創建 RequestManager
  3. 如果 with 方法的參數爲 Context,則會判斷其來源是否屬於 FragmentActivityActivity,則按照上面的邏輯進行處理,否則最終調用 getApplicationManager(Context) 方法創建 RequestManager
  4. 如果在子線程或者系統版本小於17,則調用getApplicationManager(Context) 方法創建 RequestManager
    同時,由supportFragmentGet可知,一個Activity對應一個RequestManager。
5. RequestManager生命週期

通過RequestManagerRetriever.get創建requestManager,通過requestManagerActivityGlide生命週期綁定。

 //RequestManager構造函數
 RequestManager(...) {
    //在主線程綁定Glide和Activity的生命週期
    if (Util.isOnBackgroundThread()) {
      mainHandler.post(addSelfToLifecycle);
    } else {
      lifecycle.addListener(this);
    }
    lifecycle.addListener(connectivityMonitor);
    defaultRequestListeners =
        new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
    setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
    glide.registerRequestManager(this);
 }
  
private final Runnable addSelfToLifecycle =
  new Runnable() {
	@Override
	public void run() {
	  //切換到主線程
	  lifecycle.addListener(RequestManager.this);
	}
  };
  
 //RequestManager中LifecycleLister實現
 public class RequestManager
    implements ComponentCallbacks2, LifecycleListener, ModelTypes<RequestBuilder<Drawable>> {
	...
	//開始暫停的請求
	public void onStart() {
		resumeRequests();
	}
	//停止所有的請求
	@Override
	public void onStop() {
		pauseRequests();
	}
	//關閉所以的請求
	@Override
	public void onDestroy() {
		requestTracker.clearRequests();
	}
	...
}

通過上面 RequestManagerRetrieverResquestManager 的介紹,我們知道創建 RequestManager 時需要一個 FragmentManager 參數(全局 RequestManager 除外),那麼再創建 RequestManager 時會先創建一個不可見的 RequestManagerFragment ,通過 FragmentMamager加入到當前頁面,用這個不可見的 Fragment 即可檢測頁面的生命週期,進而將Glide和頁面生命週期綁定。

6. Registry

Registry(com.bumptech.glide.Registry)是用來註冊管理任務執行對象的管理類,可以簡單理解爲:Registry是一個工廠,而其中所有註冊的對象都是一個工廠員工,當任務分發時,根據當前任務的性質,分發給相應員工進行處理。該類可細分爲:ModelLoaderRegistryEncoderRegistryResourceDecoderRegistryResourceEncoderRegistryDataRewinderRegistryTranscoderRegistryImageHeaderParserRegistry共七種。Registry通過各個細分的管理類通過HashMap或者List來管理執行類及其執行方法的對應關係。

public class Registry {
  @NonNull
  @SuppressWarnings("unchecked")
  public <X> Encoder<X> getSourceEncoder(@NonNull X data) throws 		NoSourceEncoderAvailableException {
      //根據data通過encoderRegistry來獲取對於的encoder
    Encoder<X> encoder = encoderRegistry.getEncoder((Class<X>) data.getClass());
    if (encoder != null) {
      return encoder;
    }
    throw new NoSourceEncoderAvailableException(data.getClass());
  } 
    
  @NonNull
  public <Data> Registry append(@NonNull Class<Data> dataClass, @NonNull Encoder<Data> encoder) {
     //保存dataClass和encoder對應關係到encoderRegistry工廠
    encoderRegistry.append(dataClass, encoder);
    return this;
  }
} 
public class EncoderRegistry {
      private final List<Entry<?>> encoders = new ArrayList<>();
    
     @Nullable
  public synchronized <T> Encoder<T> getEncoder(@NonNull Class<T> dataClass) {
    for (Entry<?> entry : encoders) {
      if (entry.handles(dataClass)) {
        return (Encoder<T>) entry.encoder;
      }
    }
    return null;
  }
}
7. Glide.with小結

根據上面分析,彙總成下面流程圖:
Glide流程
從圖上可以看到,Glide.with主要完成:

  1. 各類初始化,主要包括:線程池、緩存、EnginerequestManagerregisterglideContext
  2. 創建透明Fragment, 將Glide和視圖生命週期進行綁定。
load(url)
1.RequestManager.load
public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
    return asDrawable().load(bitmap);
  }
2.asDrawable()
@RequestManager.java
public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
}
//最終返回了一個RequestBuilder
public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
}
protected RequestBuilder(...) {
    this.glide = glide;
    this.requestManager = requestManager;
    this.transcodeClass = transcodeClass;
    this.context = context;
    this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
    this.glideContext = glide.getGlideContext();
    //初始化請求回調
    initRequestListeners(requestManager.getDefaultRequestListeners());
    apply(requestManager.getDefaultRequestOptions());
  }
3.load(string)
@RequestBuilder.java
public RequestBuilder<TranscodeType> load(@Nullable String string) {
    return loadGeneric(string);
}
//將url賦值給RequestBuilder.model
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
    this.model = model;
    isModelSet = true;
    return this;
  }

可以看到,load主要是創建RequestBuilder並設置請求的URL(model),並記錄了URL已設置的狀態。
到此,我們可以總結出 RequestManager 兩個主要作用:

  1. 創建 RequestBuilder,用於保存請求URL和初始化請求回調;
  2. 通過綁定頁面生命週期來管理請求的啓動結束等
into(target)
1.RequestBuilder.into
@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
	Util.assertMainThread();
	Preconditions.checkNotNull(view);
	BaseRequestOptions<?> requestOptions = this;
	//ImageView默認ScaleType爲FIT_CENTER,Glide可以通過dontTransform()或者transform(...)來關閉或使用圖片變化
	if (!this.isTransformationSet() && this.isTransformationAllowed() && view.getScaleType() != null) {
		switch(view.getScaleType()) {
		case CENTER_CROP:
			requestOptions = this.clone().optionalCenterCrop();
			break;
		case CENTER_INSIDE:
			requestOptions = this.clone().optionalCenterInside();
			break;
		case FIT_CENTER: 
		case FIT_START:
		case FIT_END:
			requestOptions = this.clone().optionalFitCenter();
			break;
		case FIT_XY:
			requestOptions = this.clone().optionalCenterInside();
		case CENTER:
		case MATRIX:
		}
	}
	
    //根據transcodeClass生成對應的ViewTarget,並指定RequestBuilder.into回調主線程執行
	return (ViewTarget)this.into(this.glideContext.buildImageViewTarget(view, this.transcodeClass), (RequestListener)null, (BaseRequestOptions)requestOptions, Executors.mainThreadExecutor());
}
2.GlideContext.buildImageViewTarget
return this.imageViewTargetFactory.buildTarget(imageView, transcodeClass);
3. ImageViewTargetFactory.buidTarget
@NonNull
public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view, @NonNull Class<Z> clazz) {
	if (Bitmap.class.equals(clazz)) {
		return new BitmapImageViewTarget(view);
	} else if (Drawable.class.isAssignableFrom(clazz)) {
		return new DrawableImageViewTarget(view);
	} else {
		throw new IllegalArgumentException("Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
	}
}

根據這段代碼可知,glideContext.buildImageViewTarget 通過傳入class類型不同,分別生成不同的ImageVieTarget,傳入Bitmap則生成BitmapImageViewTarget, 傳入Drawable則生成DrawableImageViewTarget

4. RequestBuilder.into
private <Y extends Target<TranscodeType>> Y into(@NonNull Y target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> options, Executor callbackExecutor) {
	Preconditions.checkNotNull(target);
	if (!this.isModelSet) {
		throw new IllegalArgumentException("You must call #load() before calling #into()");
	} else {
		// -->1. 建立請求
		Request request = this.buildRequest(target, targetListener, options, callbackExecutor);
		Request previous = target.getRequest();
		if (request.isEquivalentTo(previous) && !this.isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
			if (!((Request)Preconditions.checkNotNull(previous)).isRunning()) {
				previous.begin();
			}
			return target;
		} else {
			this.requestManager.clear(target);
			target.setRequest(request);
             // -->2. 請求追蹤
			this.requestManager.track(target, request);
			return target;
		}
	}
}

RequestBuilder.into的實現主要是buildRequest建立請求和requestManager.track請求追蹤,下面我們將重點分析這兩部分。
buildRequest

// 1. 建立請求
private Request buildRequest(Target<TranscodeType> target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) {
	// -->1.1 通過遞歸調用創建請求
	return this.buildRequestRecursive(new Object(), target, targetListener, (RequestCoordinator)null, this.transitionOptions, requestOptions.getPriority(), requestOptions.getOverrideWidth(), requestOptions.getOverrideHeight(), requestOptions, callbackExecutor);
}
// 1.1 通過遞歸調用創建請求
private Request buildRequestRecursive(Object requestLock, Target<TranscodeType> target, @Nullable RequestListener<TranscodeType> targetListener, @Nullable RequestCoordinator parentCoordinator, TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority, int overrideWidth, int overrideHeight, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) {
	// 判斷當前request是否需要帶error
	ErrorRequestCoordinator errorRequestCoordinator = null;
	if (this.errorBuilder != null) {
		//errorBuilder不爲空,此處爲[標記1]遞歸調用
		errorRequestCoordinator = new ErrorRequestCoordinator(requestLock, (RequestCoordinator)parentCoordinator);
		parentCoordinator = errorRequestCoordinator;
	}
	// --> 1.2 創建帶縮略圖的請求
	Request mainRequest = this.buildThumbnailRequestRecursive(requestLock, target, targetListener, (RequestCoordinator)parentCoordinator, transitionOptions, priority, overrideWidth, overrideHeight, requestOptions, callbackExecutor);
	if (errorRequestCoordinator == null) {
		//不帶error直接返回mainRequest
		return mainRequest;
	} else {
		int errorOverrideWidth = this.errorBuilder.getOverrideWidth();
		int errorOverrideHeight = this.errorBuilder.getOverrideHeight();
		if (Util.isValidDimensions(overrideWidth, overrideHeight) && !this.errorBuilder.isValidOverride()) {
			errorOverrideWidth = requestOptions.getOverrideWidth();
			errorOverrideHeight = requestOptions.getOverrideHeight();
		}
		// [標記1] 回調當前方法,構建帶error的請求
		Request errorRequest = this.errorBuilder.buildRequestRecursive(requestLock, target, targetListener, errorRequestCoordinator, this.errorBuilder.transitionOptions, this.errorBuilder.getPriority(), errorOverrideWidth, errorOverrideHeight, this.errorBuilder, callbackExecutor);
		errorRequestCoordinator.setRequests(mainRequest, errorRequest);
		return errorRequestCoordinator;
	}
}
// 1.2 創建帶縮略圖的請求
private Request buildThumbnailRequestRecursive(Object requestLock, Target<TranscodeType> target, RequestListener<TranscodeType> targetListener, @Nullable RequestCoordinator parentCoordinator, TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority, int overrideWidth, int overrideHeight, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) {
	if (this.thumbnailBuilder != null) { //thumbnailBuilder不不爲空
		if (this.isThumbnailBuilt) {
			throw new IllegalStateException("You cannot use a request as both the main request and a thumbnail, consider using clone() on the request(s) passed to thumbnail()");
		} else {
			// 獲取縮略圖配置
			TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions = this.thumbnailBuilder.transitionOptions;
			if (this.thumbnailBuilder.isDefaultTransitionOptionsSet) {
				thumbTransitionOptions = transitionOptions;
			}
			Priority thumbPriority = this.thumbnailBuilder.isPrioritySet() ? this.thumbnailBuilder.getPriority() : this.getThumbnailPriority(priority);
			int thumbOverrideWidth = this.thumbnailBuilder.getOverrideWidth();
			int thumbOverrideHeight = this.thumbnailBuilder.getOverrideHeight();
			if (Util.isValidDimensions(overrideWidth, overrideHeight) && !this.thumbnailBuilder.isValidOverride()) {
				thumbOverrideWidth = requestOptions.getOverrideWidth();
				thumbOverrideHeight = requestOptions.getOverrideHeight();
			}
			
			// 創建ThumbnailRequestCoordinator對象
			ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(requestLock, parentCoordinator);
			// 創建原圖片請求對象
			Request fullRequest = this.obtainRequest(requestLock, target, targetListener, requestOptions, coordinator, transitionOptions, priority, overrideWidth, overrideHeight, callbackExecutor);
			this.isThumbnailBuilt = true;
			// 用遞歸方式創建縮略圖請求
			Request thumbRequest = this.thumbnailBuilder.buildRequestRecursive(requestLock, target, targetListener, coordinator, thumbTransitionOptions, thumbPriority, thumbOverrideWidth, thumbOverrideHeight, this.thumbnailBuilder, callbackExecutor);
			this.isThumbnailBuilt = false;
			// 將原圖片請求和縮略圖請求打包到ThumbnailRequestCoordinator中
			coordinator.setRequests(fullRequest, thumbRequest);
			return coordinator;
		}
	} else if (this.thumbSizeMultiplier != null) {  /縮略圖縮放比例不爲空
		ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(requestLock, parentCoordinator);
		Request fullRequest = this.obtainRequest(requestLock, target, targetListener, requestOptions, coordinator, transitionOptions, priority, overrideWidth, overrideHeight, callbackExecutor);
		BaseRequestOptions<?> thumbnailOptions = requestOptions.clone().sizeMultiplier(this.thumbSizeMultiplier);
		Request thumbnailRequest = this.obtainRequest(requestLock, target, targetListener, thumbnailOptions, coordinator, transitionOptions, this.getThumbnailPriority(priority), overrideWidth, overrideHeight, callbackExecutor);
		coordinator.setRequests(fullRequest, thumbnailRequest);
		return coordinator;
	} else { //沒有縮略圖,直接返回原圖片請求,通過obtainRequest最終返回一個SingleRequest對象
		return this.obtainRequest(requestLock, target, targetListener, requestOptions, parentCoordinator, transitionOptions, priority, overrideWidth, overrideHeight, callbackExecutor);
	}
}

代碼中fullRequest表示原始的請求,thumbRequest表示縮略圖請求,mainRequest表示打包了fullRequest和thumbRequest得請求,errorRequest錯誤重試請求;具體流程參考下面流程圖,可以方便理解:
request創建流程圖
上面我們提到,最終得到得是一個SingleRequest得對象,SingleRequest以來關係如下:

public final class SingleRequest<R> implements Request, SizeReadyCallback, ResourceCallback
public interface Request {
    void begin();
	.......
}
public interface SizeReadyCallback {
    void onSizeReady(int var1, int var2);
}
public interface ResourceCallback {
    void onResourceReady(Resource<?> var1, DataSource var2);
    ......
}

onSizeReady()和begin()是SingleRequest最重要得兩個實現方法,相關方法得調用在requestTracker種,下面我們將分析RequstBuilder得第二個重點requestManager.track

5.requestManager.track
// 2.追蹤Request
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    // -->2.1 將target保存到targetTracker中
    this.targetTracker.track(target);
    // -->2.2 運行請求
    this.requestTracker.runRequest(request);
}
// 2.1 @TargetTracker.java
private final Set<Target<?>> targets = Collections.newSetFromMap(new WeakHashMap());
public void track(@NonNull Target<?> target) {
 	將tartget加入set中
    this.targets.add(target);
}
// 2.2 @RequestTracker.java
private final Set<Request> requests = Collections.newSetFromMap(new WeakHashMap());
private final List<Request> pendingRequests = new ArrayList();
public void runRequest(@NonNull Request request) {
    this.requests.add(request);
    if (!this.isPaused) {
        // -->2.3調用SingleRequest.begin()方法開始請求
        request.begin();
    } else {
        request.clear();
        if (Log.isLoggable("RequestTracker", 2)) {
            Log.v("RequestTracker", "Paused, delaying request");
        }
        //如果是暫停狀態,將請求加入pending隊列中
        this.pendingRequests.add(request);
    }
}
// 2.3 開始請求 @SingleRequest.java
public void begin() {
    synchronized(this.requestLock) {
       ......
            if (Util.isValidDimensions(this.overrideWidth, this.overrideHeight)) {
                // -->2.4 請求開始
                this.onSizeReady(this.overrideWidth, this.overrideHeight);
            } else {
                // -->2.5 如果沒有override()方法設置固定寬高,根據imageView寬高計算圖片寬高
                this.target.getSize(this);
            }
	  ......
    }
}
// 2.4 @SingleRequest
public void onSizeReady(int width, int height) {
    ......
	// -->2.6 通過引擎加載, 倒數第二個參數,傳入回調,會砸4.7中用到
            this.loadStatus = this.engine.load(this.glideContext, this.model, this.requestOptions.getSignature(), this.width, this.height, this.requestOptions.getResourceClass(), this.transcodeClass, this.priority, this.requestOptions.getDiskCacheStrategy(), this.requestOptions.getTransformations(), this.requestOptions.isTransformationRequired(), this.requestOptions.isScaleOnlyOrNoTransform(), this.requestOptions.getOptions(), this.requestOptions.isMemoryCacheable(), this.requestOptions.getUseUnlimitedSourceGeneratorsPool(), this.requestOptions.getUseAnimationPool(), this.requestOptions.getOnlyRetrieveFromCache(), this, this.callbackExecutor);
    ......
}
// 2.5 計算圖片寬高 @ViewTarget.java
void getSize(@NonNull SizeReadyCallback cb) {
    ......
        //計算完圖片寬高,最終回調2.4SingleRequest.onSizeReady方法
        cb.onSizeReady(currentWidth, currentHeight);
    ......
}
// 2.6 通過引擎加載 @Engine.java
public <R> Engine.LoadStatus load(...) {
    synchronized(this) {
        // -->2.7 加載緩存
        memoryResource = this.loadFromMemory(key, isMemoryCacheable, startTime);
        if (memoryResource == null) {
            // -->2.8 沒緩存,加載網絡資源
            return this.waitForExistingOrStartNewJob(...);
        }
    }
    // 回到到singleRequest類中
    cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
    return null;
}
// 2.7 加載緩存 @Engine.java
@Nullable
private EngineResource<?> loadFromMemory(EngineKey key, boolean isMemoryCacheable, long startTime) {
    if (!isMemoryCacheable) {
        // 如果設置爲不使用緩存,直接返回
        return null;
    } else {
        // 首先,在弱引用緩存map中查找,找到就直接返回active
        EngineResource<?> active = this.loadFromActiveResources(key);
        if (active != null) {
            if (VERBOSE_IS_LOGGABLE) {
                logWithTimeAndKey("Loaded resource from active resources", startTime, key);
            }
            return active;
        } else {
            // 接着在內存memoryCache中尋找,找到就直接返回cache
            // memoryCache在GlideBuilder.build中初始化,爲LruResourceCache上文有相關代碼
            EngineResource<?> cached = this.loadFromCache(key);
            if (cached != null) {
                if (VERBOSE_IS_LOGGABLE) {
                    logWithTimeAndKey("Loaded resource from cache", startTime, key);
                }
                return cached;
            } else {
                return null;
            }
        }
    }
}
//2.8 沒緩存,加載網絡資源 @Engine.java
private <R> Engine.LoadStatus waitForExistingOrStartNewJob(...) {
    EngineJob<?> current = this.jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
        current.addCallback(cb, callbackExecutor);
        if (VERBOSE_IS_LOGGABLE) {
            logWithTimeAndKey("Added to existing load", startTime, key);
        }
        return new Engine.LoadStatus(cb, current);
    } else {
        // 創建下載工程任務類
        EngineJob<R> engineJob = this.engineJobFactory.build(key, isMemoryCacheable, useUnlimitedSourceExecutorPool, useAnimationPool, onlyRetrieveFromCache);
         // 創建解析工作對象
        DecodeJob<R> decodeJob = this.decodeJobFactory.build(glideContext, model, key, signature, width, height, resourceClass, transcodeClass, priority, diskCacheStrategy, transformations, isTransformationRequired, isScaleOnlyOrNoTransform, onlyRetrieveFromCache, options, engineJob);
        // 存入Jobs內部維護的HashMap中
        this.jobs.put(key, engineJob);
        engineJob.addCallback(cb, callbackExecutor);
        // -->2.9 啓動請求線程
        engineJob.start(decodeJob);
        if (VERBOSE_IS_LOGGABLE) {
            logWithTimeAndKey("Started new load", startTime, key);
        }
        return new Engine.LoadStatus(cb, engineJob);
    }
}
// 2.9 啓動請求線程, 根據配置不同,使用不同的解碼線程池 @Engine.java
public synchronized void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    GlideExecutor executor = decodeJob.willDecodeFromCache() ? this.diskCacheExecutor : this.getActiveSourceExecutor();
    // -->2.10 啓動解碼任務
    executor.execute(decodeJob);
}
// 2.10 啓動解碼任務  @DecodeJob.java
public void run() {
	......
    try {
        if (!this.isCancelled) {
            // -->2.11 運行解碼任務
            this.runWrapped();
            return;
        }
    ......
}
//2.11 運行解碼任務 @DecodeJob.java
private void runWrapped() {
    switch(this.runReason) {
        case INITIALIZE: 
            // -->2.12 根據緩存策略生成對應stage,stage的推進就代表緩存的查找順序
            this.stage = this.getNextStage(DecodeJob.Stage.INITIALIZE);
            // -->2.13 根據stage生成Generator
            this.currentGenerator = this.getNextGenerator();
            // -->2.14 執行Generator的startNext()方法
            this.runGenerators();
            break;
        case SWITCH_TO_SOURCE_SERVICE:
            this.runGenerators();
            break;
        case DECODE_DATA:
            this.decodeFromRetrievedData();
            break;
        default:
            throw new IllegalStateException("Unrecognized run reason: " + this.runReason);
    }
}
    
//2.12 根據緩存策略生成對應stage  @DecodeJob.java
private DecodeJob.Stage getNextStage(DecodeJob.Stage current) {
    switch(current) {
        case RESOURCE_CACHE: //如果支持原圖尺寸,下一個state就是DATA_CACHE,否則,從DATA_CACHE開始往下判斷
            return this.diskCacheStrategy.decodeCachedData() ? DecodeJob.Stage.DATA_CACHE : this.getNextStage(DecodeJob.Stage.DATA_CACHE);
        case DATA_CACHE: //如果只讀緩存,下一個Stage爲FINISHED,否則就是SOURCE
            return this.onlyRetrieveFromCache ? DecodeJob.Stage.FINISHED : DecodeJob.Stage.SOURCE;
        case SOURCE:
        case FINISHED:
            return DecodeJob.Stage.FINISHED;
        case INITIALIZE: //如果支持多尺寸,下一個state就是RESOURCE_CACHE,否則,從RESOURCE_CACHE開始往下判斷
            return this.diskCacheStrategy.decodeCachedResource() ? DecodeJob.Stage.RESOURCE_CACHE : this.getNextStage(DecodeJob.Stage.RESOURCE_CACHE);
        default:
            throw new IllegalArgumentException("Unrecognized stage: " + current);
    }
}
    
// 2.13 根據stage獲取Generator  @DecodeJob.java
private DataFetcherGenerator getNextGenerator() {
    switch(this.stage) {
        case RESOURCE_CACHE: //緩存多尺寸
            return new ResourceCacheGenerator(this.decodeHelper, this);
        case DATA_CACHE:  //緩存原圖
            return new DataCacheGenerator(this.decodeHelper, this);
        case SOURCE: //下載遠程圖片
            return new SourceGenerator(this.decodeHelper, this);
        case FINISHED:
            return null;
        default:
            throw new IllegalStateException("Unrecognized stage: " + this.stage);
    }
}
    
//2.14 循環執行Generators的startNext()方法 @DecodeJob.java
private void runGenerators() {
	......
    while(!this.isCancelled && this.currentGenerator != null && !(isStarted = this.currentGenerator.startNext())) { //--> 2.15 執行Generator的startNext()方法
        //獲取下一個stage
        this.stage = this.getNextStage(this.stage);
        //獲取下一個Generator
        this.currentGenerator = this.getNextGenerator();
        if (this.stage == DecodeJob.Stage.SOURCE) {
            this.reschedule();
            return;
        }
    }
    ......
}
 
 // 2.15 以SourceGenerator爲例,@SourceGenerator
 public boolean startNext() {
     ......
     boolean started = false;
     while(!started && this.hasNextModelLoader()) {
         this.loadData = (LoadData)this.helper.getLoadData().get(this.loadDataListIndex++);
         // 根據緩存策略來篩選loaddata,這裏最終獲取的loaddata是HttpGlideUrlLoader,Fetcher是HttpUrlFetcher
         if (this.loadData != null && (this.helper.getDiskCacheStrategy().isDataCacheable(this.loadData.fetcher.getDataSource()) || this.helper.hasLoadPath(this.loadData.fetcher.getDataClass()))) {
             started = true;
              // -->2.16 加載數據 
             this.startNextLoad(this.loadData);
         }
     }
     return started;
 }
    
 // 2.16 加載數據 @SourceGenerator.java
 private void startNextLoad(final LoadData<?> toStart) {
     	// -->2.17通過loadData方法獲取圖片數據
        this.loadData.fetcher.loadData(this.helper.getPriority(), new DataCallback<Object>() {this.helper.getPriority(), new DataCallback<Object>() {
            public void onDataReady(@Nullable Object data) {
                if (SourceGenerator.this.isCurrentRequest(toStart)) {
                    // -->3.1 獲取數據之後回調數據到SourceGenerator進行解碼
                    SourceGenerator.this.onDataReadyInternal(toStart, data);
                }
            }
            ......
        }
 }
// 2.17 獲取圖片數據 @HttpUrlFetcher.java
public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
	......
    try {
        // -->2.18 網絡下載圖片
        InputStream result = this.loadDataWithRedirects(this.glideUrl.toURL(), 0, (URL)null, this.glideUrl.getHeaders());
        callback.onDataReady(result);
    } catch (IOException var9) {...}
	......
}
       
// 2.18 使用HttpURLConnection下載網絡圖片 @HttpUrlFetcher.java
private InputStream loadDataWithRedirects(...) throws IOException {
    if (redirects >= 5) {
        //設置最大重定向次數爲5次
        throw new HttpException("Too many (> 5) redirects!");
    } else {
        ......
        this.urlConnection.setConnectTimeout(this.timeout);
        this.urlConnection.setReadTimeout(this.timeout);
        this.urlConnection.setUseCaches(false);
        this.urlConnection.setDoInput(true);
        this.urlConnection.setInstanceFollowRedirects(false);
        this.urlConnection.connect();
        this.stream = this.urlConnection.getInputStream();
        if (this.isCancelled) {
            return null;
        } else {
            int statusCode = this.urlConnection.getResponseCode();
            if (isHttpOk(statusCode)) {
                // -->2.19請求成功,獲取圖片數據
                return this.getStreamForSuccessfulRequest(this.urlConnection);
            } else if (isHttpRedirect(statusCode)) {
                	......
                    // 重定向次數加1
                    return this.loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
                }
            } else if (statusCode == -1) {
                throw new HttpException(statusCode);
            } else {
                throw new HttpException(this.urlConnection.getResponseMessage(), statusCode);
            }
        }
    }
}
                                       
// 2.19 獲取數據流 @HttpUrlFetcher.java
private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection) throws IOException {
    if (TextUtils.isEmpty(urlConnection.getContentEncoding())) {
        int contentLength = urlConnection.getContentLength();
        this.stream = ContentLengthInputStream.obtain(urlConnection.getInputStream(), (long)contentLength);
    } else {
        if (Log.isLoggable("HttpUrlFetcher", 3)) {
            Log.d("HttpUrlFetcher", "Got non empty content encoding: " + urlConnection.getContentEncoding());
        }
        // 獲取數據流
        this.stream = urlConnection.getInputStream();
    }
    return this.stream;
}                            

終於到了圖篇下載的地方,我們最後獲取的是數據流,接下來的步驟是數據流解碼。

6.返回數據流解碼
// -->3.1 返回數據流到SourceGenerator @SourceGenerator.java
void onDataReadyInternal(LoadData<?> loadData, Object data) {
    DiskCacheStrategy diskCacheStrategy = this.helper.getDiskCacheStrategy();
    if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
        this.dataToCache = data;
        this.cb.reschedule();
    } else {
        // --> 3.2 回到DecodeJob繼續處理,會調用到decodeFromRetrievedData處理
        this.cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher, loadData.fetcher.getDataSource(), this.originalKey);
    }
}
// 3.2 處理返回數據 @DecodeJob.java
 private void decodeFromRetrievedData() {
     ......
     try {
         // -->3.3 在decodeFromFetcher中調用decodeFromFetcher處理,從數據中解碼得到資源
         resource = this.decodeFromData(this.currentFetcher, this.currentData, this.currentDataSource);
     } catch (GlideException var3) {
         var3.setLoggingDetails(this.currentAttemptingKey, this.currentDataSource);
         this.throwables.add(var3);
     }
	
     if (resource != null) {
         // -->4.1 編碼和發佈資源
         this.notifyEncodeAndRelease(resource, this.currentDataSource);
     } else {
         this.runGenerators();
     }
 }
// 3.3 @DecodeJob.java
 private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource) throws GlideException {
        LoadPath<Data, ?, R> path = this.decodeHelper.getLoadPath(data.getClass());
     	// -->3.4 將解碼任務分發給LoadPath
        return this.runLoadPath(data, dataSource, path);
}
// 3.4 將解碼任務分發給LoadPath
private <Data, ResourceType> Resource<R> runLoadPath(...) throws GlideException {
    Options options = this.getOptionsWithHardwareConfig(dataSource);
    // 將數據打包到Rewinder對象中,根據data的類型獲取對應的rewinder,這裏爲ByteBufferRewinder
    DataRewinder rewinder = this.glideContext.getRegistry().getRewinder(data);
    Resource var6;
    try {
        // -->3.5 LoadPath.load -> LoadPath.loadWithExceptionList -> DecodePath.decodeResource ->
        // DecodePath.decodeResourceWithList
        var6 = path.load(rewinder, options, this.width, this.height, new DecodeJob.DecodeCallback(dataSource));
    } finally {
        rewinder.cleanup();
    }
    return var6;
}
// 3.5 @DecodePath.java
private Resource<ResourceType> decodeResourceWithList(...) throws GlideException {
	......
        try {
            DataType data = rewinder.rewindAndGet();
            if (decoder.handles(data, options)) {
                data = rewinder.rewindAndGet();
                // -->3.6根據dataType使用對應的decoder,這裏decoder是ByteBufferBitmapDecoder
                result = decoder.decode(data, width, height, options);
            }
        }
    ......
        if (result == null) {
            // 如果找不到合適的decoder拋出異常,回到LoadPath.loadWithExceptionList中用下一個DecodePath處理
            throw new GlideException(this.failureMessage, new ArrayList(exceptions));
        } else {
            return result;
        }
}
// 3.6 對數據進行處理 @ByteBufferBitmapDecoder.java
public Resource<Bitmap> decode(...) throws IOException {
    InputStream is = ByteBufferUtil.toStream(source);
    // -->3.7 使用downsampler對流數據進行解碼和圖像處理等,並封裝爲Resource<Bitmap>對象返回
    return this.downsampler.decode(is, width, height, options);
}
// 3.7 使用downsampler對流數據進行解碼和圖像處理等 @Downsampler.java
private Resource<Bitmap> decode(...) throws IOException {
    BitmapResource var14;
    try {
        //Bitmap處理
        Bitmap result = this.decodeFromWrappedStreams(imageReader, bitmapFactoryOptions, downsampleStrategy, decodeFormat, preferredColorSpace, isHardwareConfigAllowed, requestedWidth, requestedHeight, fixBitmapToRequestedDimensions, callbacks);
        //打包爲Resource<Bitmap>對象返回
        var14 = BitmapResource.obtain(result, this.bitmapPool);
    } finally {
        releaseOptions(bitmapFactoryOptions);
        this.byteArrayPool.put(bytesForOptions);
    }
    return var14;
}

通過上面步驟,基本解碼流程就結束了,加下來進入解碼和發佈流程

7.解碼和發佈

解碼和發佈,就是將Bitmap顯示到ImageView,這裏的入口在notifyEncodeAndRelease中,代碼回到DecodeJob中。

// 4.1 解碼和發佈流程入口 @DecodeJob.java
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
    ......
   	// -->4.2 開始解碼和發佈
    this.notifyComplete((Resource)result, dataSource);
    // 設置stage爲ENCODE
    this.stage = DecodeJob.Stage.ENCODE;
	......
 }
 
 //4.2 開始解碼和發佈 @DecodeJob.java
 private void notifyComplete(Resource<R> resource, DataSource dataSource) {
     this.setNotifiedOrThrow();
     // -->4.3 回調EngineJob.onResourceReady
     this.callback.onResourceReady(resource, dataSource);
 }
 
 // 4.3 @EngineJob.java
 public void onResourceReady(Resource<R> resource, DataSource dataSource) {
     synchronized(this) {
     	this.resource = resource;
     	this.dataSource = dataSource;
     }
     // -->4.4
	this.notifyCallbacksOfResult();
}
// 4.4 @EngineJob.java
void notifyCallbacksOfResult() {
       ......
       // -->4.5
       while(var4.hasNext()) {
            EngineJob.ResourceCallbackAndExecutor entry = (EngineJob.ResourceCallbackAndExecutor)var4.next();
            entry.executor.execute(new EngineJob.CallResourceReady(entry.cb));
        }
}
//4.5 @EngineJob.java
static final class ResourceCallbackAndExecutor {
	while(var4.hasNext()) {
    	EngineJob.ResourceCallbackAndExecutor entry = (EngineJob.ResourceCallbackAndExecutor)var4.next();
        entry.executor.execute(new EngineJob.CallResourceReady(entry.cb)); //-->4.6
    }
}
//4.6 @EngineJob.java
private class CallResourceReady implements Runnable {
    public void run() {
    ......
    // -->4.7 
    EngineJob.this.callCallbackOnResourceReady(this.cb);
	......
    }
}
//4.7 @EngineJob.java
void callCallbackOnResourceReady(ResourceCallback cb) {
	try {
		//-->4.8 這裏的回調cb指的傳的就是SingleRequest,在2.6中 SingleRequest中把自身作爲倒數第二個參數傳入engine.load中
    	cb.onResourceReady(this.engineResource, this.dataSource);
     } catch (Throwable var3) {
        throw new CallbackException(var3);
     }
}
// 4.8 @SingleRequest.java
private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
    ......
      if (!anyListenerHandledUpdatingTarget) {
        Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource);
        //-->4.9 這裏的target便是我們調用之初建立的BitmapImageViewTarget,具體的實現方法在其父類ImageViewTarget中
        target.onResourceReady(result, animation);
      }
	......
  }
// 4.9 @ImageViewTarget.java
 @Override
  public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
    if (transition == null || !transition.transition(resource, this)) {
      setResourceInternal(resource); //-->4.10
    } else {
      maybeUpdateAnimatable(resource);
    }
  }
  
  //4.10 @ImageViewTarget.java
  private void setResourceInternal(@Nullable Z resource) {
  	//-->4.11 抽象方法,具體實現在子類BitmapImageViewTarget中
    setResource(resource);
    maybeUpdateAnimatable(resource);
  }
  
  //4.11 @BitmapImageView.java
  @Override
  protected void setResource(Bitmap resource) {
  	//終於看到了Bitmap設置到imageView上!
    view.setImageBitmap(resource);
  }
 

從上面分析流程可知,Gilde大多數的處理流程都在into方法中執行,請求,數據,編碼解碼,以及最後的顯示,這份源碼值得我們多讀幾次,細細品味。
文章雖然很長,但是我還是決定不分篇,以保證加載流程閱讀的完整度,也方便後期檢索方便。很感謝看到最後的各位~

參考
Glide4.8源碼拆解(二)核心加載流程
Glide4.10 緩存
LruCache緩存機制

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章