Glide 4.7.1源碼分析--啓動加載 into(view)

Glide源碼分析 – 啓動圖片加載流程

// 在 RequestBuilder.into()之前必須調用load()系列方法,設置model
// 重載的一系列into()方法最終都調用
/* private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @NonNull RequestOptions options) 
      */
 Glide.with(context)
                .load(url)
                .apply(requestOptions)
                .into(iv);

在這裏分析 參數是 imageView的 RequestBuilder.into(imageview)
① public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view)

public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    Util.assertMainThread();
    Preconditions.checkNotNull(view);

    RequestOptions requestOptions = this.requestOptions;
    if (!requestOptions.isTransformationSet()
        && requestOptions.isTransformationAllowed()
        && view.getScaleType() != null) {
        // 創建縮放模式
      switch (view.getScaleType()) {
        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;
        case CENTER:
        case MATRIX:
        default:
      }
    }
    // glideContext.buildImageViewTarget(view, transcodeClass)
    // 創建返回目標,根據
    //Glide.with(context).asBitmap()
//    Glide.with(context).asDrawable() 返回
    /*
   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);
    } else {
      throw new IllegalArgumentException(
          "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
    }
  }
  */
    return into(
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions);
  }

②進入 public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view)

private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @NonNull RequestOptions options) {
    Util.assertMainThread();
    Preconditions.checkNotNull(target);
    // 這裏表明 調用 into()之前必須調用load()設置model
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }
    options = options.autoClone();
    // 創建本次請求對象,跟蹤發現最終調用SingleRequest.obtain()
    // 返回 SingleRequest對象
    Request request = buildRequest(target, targetListener, options);
    // 獲取上次請求
    Request previous = target.getRequest();
//如果本次請求與上次請求相同,並且未設置跳過內存緩存
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
        // 回收本次請求
      request.recycle();
      //如果 previous 已經請求完畢,會返回false
      if (!Preconditions.checkNotNull(previous).isRunning()) {
      //使用 previous 去請求,如果有緩存會使用緩存
        previous.begin();
      }
      return target;
    }
   //這裏會回收 target 的上次請求對象
	requestManager.clear(target);
	//給 target 設置本次請求的 request
	target.setRequest(request);
	//把請求塞入隊列,根據頁面是否在前臺,來處理請求
	requestManager.track(target, request);
    return target;
  }

② 開始請求 Request.begin()

public void begin() {
    ...
    ...
    // 尺寸有效
    if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
    // 真正請求加載圖片
      onSizeReady(overrideWidth, overrideHeight);
    } else {
    // 獲取尺寸,尺寸有效會回調  onSizeReady(overrideWidth, overrideHeight)
      target.getSize(this);
    }
  }
// 這裏開始加載圖片
 public void onSizeReady(int width, int height) {
   ...
   // 引擎類開始加載
    loadStatus = engine.load(
        glideContext,
        model,
        requestOptions.getSignature(),
        this.width,
        this.height,
        requestOptions.getResourceClass(),
        transcodeClass,
        priority,
        requestOptions.getDiskCacheStrategy(),
        requestOptions.getTransformations(),
        requestOptions.isTransformationRequired(),
        requestOptions.isScaleOnlyOrNoTransform(),
        requestOptions.getOptions(),
        requestOptions.isMemoryCacheable(),
        requestOptions.getUseUnlimitedSourceGeneratorsPool(),
        requestOptions.getUseAnimationPool(),
        requestOptions.getOnlyRetrieveFromCache(),
        this);
  }

③ Engine 開始執行圖片加載邏輯

public class Engine implements EngineJobListener, ... {
	
	/* 弱引用實現 活動緩存
	 * activeResources 是Glide通過引用計數實現 Bitmap複用的關鍵
	 */
	private final ActiveResources activeResources;
	
	/* 內存緩存 LruCache 實現
	 * LruCache 內部是一個 LinkedHashMap,使用LRU 最近最少訪問算法,淘汰緩存
	 */
	private final MemoryCache cache;
	
	private final LazyDiskCacheProvider diskCacheProvider;//磁盤緩存
	
	public <R> LoadStatus load(...) {
		//到這裏還是主線程
		Util.assertMainThread();
		/* 根據請求信息(包括load(model)方法的參數、圖片寬高等),構建 key
		 * 這個key,也是用於 memoryCache  diskCache 的key
		 */
		EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
			resourceClass, transcodeClass, options);
		
		//從 活動緩存 activeResources 去拿圖片
		EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
		if (active != null) {
			//從活動緩存中找到圖片後,回調 onResourceReady() 方法	
			cb.onResourceReady(active, DataSource.MEMORY_CACHE);
			...
			return null;
		}
		/* 活動緩存 activeResources 中沒找到圖片
		 * 去內存緩存 cache 中獲取圖片
		 */
		EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
		if (cached != null) {
			//從內存緩存中找到圖片後,回調 onResourceReady() 方法	
			cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
			...
			return null;
		}
		//根據key 獲取 EngineJob
		EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
		if (current != null) {
			current.addCallback(cb);
			...
			return new LoadStatus(cb, current);
		}
		//構建 EngineJob
		EngineJob<R> engineJob =
			engineJobFactory.build(
				key,
				isMemoryCacheable,
				useUnlimitedSourceExecutorPool,
				useAnimationPool,
				onlyRetrieveFromCache);
		//構建 DecodeJob
		DecodeJob<R> decodeJob =
			decodeJobFactory.build(
				glideContext,
				model,
				key,
				signature,
				width,
				height,
				resourceClass,
				transcodeClass,
				priority,
				diskCacheStrategy,
				transformations,
				isTransformationRequired,
				isScaleOnlyOrNoTransform,
				onlyRetrieveFromCache,
				options,
				engineJob);
		//根據key 緩存 EngineJob
		jobs.put(key, engineJob);
		engineJob.addCallback(cb);
		
		engineJob.start(decodeJob);
		...
		return new LoadStatus(cb, engineJob);
	}			
}
發佈了38 篇原創文章 · 獲贊 8 · 訪問量 8630
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章