重學Android——Glide4.x源碼分析(1)

重學Android——Glide4.x源碼分析(2)java

Glide4.x

先來講下世面上經常使用的三種圖片加載框架Picasso,Glide,Frescoandroid

Picasso與Glide相比:git

  • 類似——api上的調用差很少,都支持內存緩存,glide是picasso的升級,性能有必定的提高
  • 差別
    • 緩存不一樣,picasso2級緩存,沒有磁盤緩存,Glide三級緩存,內存-磁盤-網絡的優先級加載黑乎乎。
    • Picasso默認加載的圖片格式是ARGB-8888,Glide默認是RGB-565,內存開銷節省小一半
    • Picasso是加載全尺寸圖片到內存中,下次在任何imageView中加載圖片時,先取全尺寸圖片,從新調整大小,再存緩存。而Glide是按ImageView的大小緩存的,爲每種大小緩存一次。Glide這種方式是空間換時間,大小几乎是picasso的2倍
    • 生命週期問題,Glide的with方法圖片加載會和Activity與Fragment的生命週期一致
    • Glide能夠加載GIF
    • Picasso包特別小,100k左右,方法法爲850,glide大概500k,2700個方法。

Frescogithub

  • 優勢:
    • 圖片存儲在安卓系統匿名共享內存區,而不是虛擬機的堆內存,圖片的中間緩衝數據也存放在本地堆內存,因此應用有更多的內存空間使用。不容易OOM,減小GC回收
    • 漸近式加載,支持圖片從模糊到清晰,用戶體驗極好
    • 圖片能夠以任意爲中心點顯示在ImageView
    • JPEG圖片改變大小也是在native進行,不在虛擬機堆內存,一樣減小OOM
    • 對GIF支持友好
  • 缺點
    • 包太大,2-3M
    • 用法複雜
    • 底層都是C/C++,源碼閱讀有挑戰性

小結

Glide能作Picasso能作的全部事情,更快,能處理大型圖片流,通常Glide是首選;Fresco當使用圖片很是多的應用時,它的優點很是明顯api

Glide的基本使用

implementation ("com.github.bumptech.glide:glide:4.9.0") {
        exclude group: "com.android.support"
    }
    annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
複製代碼
Glide.with(this)
        .load("http://pic37.nipic.com/20140113/8800276_184927469000_2.png")
        .into(imageView);

<uses-permission android:name="android.permission.INTERNET" />
複製代碼

須要注意的是,咱們在Android9.0以上使用,用的http請求的話,須要在AndroidMainfest中緩存

<application
        ...
        android:usesCleartextTraffic="true">
複製代碼

緣由是android9.0之後,默認禁止http請求的。網絡

Glide源碼

Glide.with(實例化Glide並獲取RequestManager)

先看Glide.with()方法app

@NonNull
  public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
  }

  @NonNull
  public static RequestManager with(@NonNull Activity activity) {
    return getRetriever(activity).get(activity);
  }

  @NonNull
  public static RequestManager with(@NonNull FragmentActivity activity) {
    return getRetriever(activity).get(activity);
  }

  @NonNull
  public static RequestManager with(@NonNull Fragment fragment) {
    return getRetriever(fragment.getActivity()).get(fragment);
  }

  @SuppressWarnings("deprecation")
  @Deprecated
  @NonNull
  public static RequestManager with(@NonNull android.app.Fragment fragment) {
    return getRetriever(fragment.getActivity()).get(fragment);
  }

  @NonNull
  public static RequestManager with(@NonNull View view) {
    return getRetriever(view.getContext()).get(view);
  }
複製代碼

能夠看到,with方法有多個重載方法,並且都是先調用了getRetriever這個方法,那麼咱們先看這個方法的源碼框架

@NonNull
  private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    ...
    return Glide.get(context).getRequestManagerRetriever();
  }
複製代碼

從源碼看,直接是調用Glide的get()方法,而後再調用getRequestManagerRetrieveride

先看get方法

@NonNull
  public static Glide get(@NonNull Context context) {
    if (glide == null) {
      synchronized (Glide.class) {
        if (glide == null) {
          checkAndInitializeGlide(context);
        }
      }
    }

    return glide;
  }
複製代碼

一看原來Glide是單例,只有第一次會實例化,經過Builder模式實例化Glide對象,初始化後調用getRequestManagerRetriever方法來獲得RequestManagerRetriever對象。

生命週期管理

那麼問題又回到了getRetriever(xxx).get(xxx);這裏,當getRetriever獲得了RequestManagerRetriever對象,咱們繼續看後面的get方法

//get方法也和with同樣,有多個對應的重載
	@NonNull
    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)) {
            //直接返回ApplicationManager
            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());
            }
        }
		//傳入的context爲ApplicationContext
        return getApplicationManager(context);
    }

	//get(Activity/fragement)邏輯都差很少的,這裏只拿getFragmentActivity來說
    @NonNull
    public RequestManager get(@NonNull FragmentActivity activity) {
        if (Util.isOnBackgroundThread()) {
            //後臺時,就調用get(context)
            return get(activity.getApplicationContext());
        } else {
            assertNotDestroyed(activity);
            //前臺可見,建立一個FragmentManager
            FragmentManager fm = activity.getSupportFragmentManager();
            return supportFragmentGet(
                activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
        }
    }

    @NonNull
    private RequestManager supportFragmentGet( @NonNull Context context, @NonNull FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
        //獲取RequestManager
        SupportRequestManagerFragment current =
            getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
            // TODO(b/27524013): Factor out this Glide.get() call.
            Glide glide = Glide.get(context);
            //若是獲得requestManager爲空,建立requestManager,並把Lifecycle傳了進去
            requestManager =
                factory.build(
                glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
            //緩存這個requestManager
            current.setRequestManager(requestManager);
        }
        return requestManager;
    }

	//建立並添加一個SupportRequestManagerFragment
    @NonNull
    private SupportRequestManagerFragment getSupportRequestManagerFragment( @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
        SupportRequestManagerFragment current =
            (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
            current = pendingSupportRequestManagerFragments.get(fm);
            if (current == null) {
                current = new SupportRequestManagerFragment();
                current.setParentFragmentHint(parentHint);
                if (isParentVisible) {
                    current.getGlideLifecycle().onStart();
                }
                pendingSupportRequestManagerFragments.put(fm, current);
                //在這裏,使用fragmentManager添加了一個隱藏的無界面Fragment
                fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
                handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
            }
        }
        return current;
    }
複製代碼

能夠看到,get方法的重載方法不少,可是核心都是同樣的的,就是返回兩種requestManager,1. ApplicationManager,它的生命週期與應用同步,應用退出,Glide也退出;2. 附加在Fragment之上的requestManager,經過這個fragment,綁定了對應的生命週期,這樣就能夠在Activity銷燬時往上加載了,RxPermission也是這麼設計的。

public class SupportRequestManagerFragment extends Fragment {
  private static final String TAG = "SupportRMFragment";
  private final ActivityFragmentLifecycle lifecycle;  
  ...
  @Override
  public void onAttach(Context context) {
    super.onAttach(context);
    try {
      registerFragmentWithRoot(getActivity());
    } catch (IllegalStateException e) {
      // OnAttach can be called after the activity is destroyed, see #497.
      if (Log.isLoggable(TAG, Log.WARN)) {
        Log.w(TAG, "Unable to register fragment with root", e);
      }
    }
  }

  @Override
  public void onDetach() {
    super.onDetach();
    parentFragmentHint = null;
    unregisterFragmentWithRoot();
  }

  @Override
  public void onStart() {
    super.onStart();
    lifecycle.onStart();
  }

  @Override
  public void onStop() {
    super.onStop();
    lifecycle.onStop();
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    lifecycle.onDestroy();
    unregisterFragmentWithRoot();
  }
...
}
複製代碼

能夠看到,SupportRequestManagerFragment就是這麼設計的,注入了一個生命週期監聽器ActivityFragmentLifecycle,並在Fragment的各個生命週期中,調用了對應的方法。

class ActivityFragmentLifecycle implements Lifecycle {
  ...
  @Override
  public void addListener(@NonNull LifecycleListener listener) {
    lifecycleListeners.add(listener);

    if (isDestroyed) {
      listener.onDestroy();
    } else if (isStarted) {
      listener.onStart();
    } else {
      listener.onStop();
    }
  }

  @Override
  public void removeListener(@NonNull LifecycleListener listener) {
    lifecycleListeners.remove(listener);
  }

  void onStart() {
    isStarted = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStart();
    }
  }

  void onStop() {
    isStarted = false;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStop();
    }
  }

  void onDestroy() {
    isDestroyed = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onDestroy();
    }
  }
}
複製代碼

能夠看到,在ActivityFragmentLifecycle會緊接着調用lifecycleListener監聽器,而這個監聽器其實就是RequestManager。

最後,能夠看到,生命週期已與requestManager進行了綁定。

RequestBuilder

load

接下來咱們看load方法的源碼

public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
  }
複製代碼

先來看前面的asDrawable

public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }
  public <ResourceType> RequestBuilder<ResourceType> as( @NonNull Class<ResourceType> resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }
複製代碼

其實就至關於new RequestBuilder,那再看load

public RequestBuilder<TranscodeType> load(@Nullable String string) {
    return loadGeneric(string);
  }
  @NonNull
  private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
    this.model = model;
    isModelSet = true;
    return this;
  }
複製代碼

能夠看到load方法很是簡單,實際上是建立了RequestBuilder,並把傳遞進來的參數url賦值給RequestBuilder中。

into方法實現資源加載並設置到target中

再看into方法

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

    BaseRequestOptions<?> requestOptions = this;
    if (!requestOptions.isTransformationSet()
        && requestOptions.isTransformationAllowed()
        && view.getScaleType() != null) {
      // Clone in this method so that if we use this RequestBuilder to load into a View and then
      // into a different target, we don't retain the transformation applied based on the previous
      // View's scale type.
      //這些都與ImageView的scaleType相關,是轉換邏輯,與咱們關心的代碼流程無關,能夠不用關心
      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:
          // Do nothing.
      }
    }

    //真正執行的代碼在這
    return into(
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions,
        Executors.mainThreadExecutor());
  }
複製代碼

分析源碼能夠知道,它的內部調用了into的重載方法

咱們先看裏面的參數方法glideContext.buildImageViewTarget(view, transcodeClass),

@NonNull
  public <X> ViewTarget<ImageView, X> buildImageViewTarget( @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
  }
  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)");
    }
  }
複製代碼

能夠看到,返回了ViewTarger,還記得上面咱們看到的asDrawable麼,說明是DrawableImageViewTarget,接下來再看外層的into方法

private <Y extends Target<TranscodeType>> Y into( @NonNull Y target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> options, Executor callbackExecutor) {
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

      //建立request
    Request request = buildRequest(target, targetListener, options, callbackExecutor);
	//獲取targert以前的請求任務(若是有的話)
    Request previous = target.getRequest();
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
        //新構建的request上一個相等,而且設置了緩存以及沒有執行完成
        //釋放新的request
      request.recycle();
      // If the request is completed, beginning again will ensure the result is re-delivered,
      // triggering RequestListeners and Targets. If the request is failed, beginning again will
      // restart the request, giving it another chance to complete. If the request is already
      // running, we can let it continue running without interruption.
      if (!Preconditions.checkNotNull(previous).isRunning()) {
          //當舊的request沒有在運行。執行它的begin
        // Use the previous request rather than the new one to allow for optimizations like skipping
        // setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
        // that are done in the individual Request.
        previous.begin();
      }
      return target;
    }

      // 清除先Target以前的全部任務並釋放資源
    requestManager.clear(target);
      //把新的request設置給target
    target.setRequest(request);
    //在這裏執行request,下載圖片任務
    requestManager.track(target, request);

    return target;
  }

  private boolean isSkipMemoryCacheWithCompletePreviousRequest( BaseRequestOptions<?> options, Request previous) {
      //是否設置緩存以及上一次是否執行完成
    return !options.isMemoryCacheable() && previous.isComplete();
  }
複製代碼

這裏主要作了兩件事:

  1. 經過buildRequest構建了一個request
  2. 獲取target的上一個request對象,與新的request對比,並檢測是否採用了緩存及target的上次請求是否完成
    1. 兩個對象相等,而且options採用了緩存或target上一次沒有請求完,則將新的request回收,並判斷target的request是否還在運行,沒有的話begin,並返回
    2. 兩個對象不相等,或者option沒有使用緩存和target請求完成了,清除target的之間設置,並將新的request對象設置給target,經過track方法啓動request請求。

再來看requestManager的track方法

synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
  }

  public void track(@NonNull Target<?> target) {
    targets.add(target);
  }

  public void runRequest(@NonNull Request request) {
    requests.add(request);
    if (!isPaused) {
        //當處於前臺可見時,調用request的begin
      request.begin();
    } else {
      request.clear();
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Paused, delaying request");
      }
        //先不執行request,只把它加入到一個準備隊列
      pendingRequests.add(request);
    }
  }
複製代碼

可的看到,track方法是先將target添加到targetTracker類的targets集合中,而後運行request的begin方法。

到這裏,其實圖片加載網絡資源的流程已經完成了大半了。接下來接着看如何加載資源並顯示到target上的。

Request實現加載資源及顯示

咱們直接點request.begin方法去跟蹤源碼,會發現Request只是一個接口,因此咱們要找到它的實現類。

那麼咱們再看上面的建立request方法

private Request buildRequest( Target<TranscodeType> target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) {
    return buildRequestRecursive(
        target,
        targetListener,
        /*parentCoordinator=*/ null,
        transitionOptions,
        requestOptions.getPriority(),
        requestOptions.getOverrideWidth(),
        requestOptions.getOverrideHeight(),
        requestOptions,
        callbackExecutor);
  }

  //參數是真雞兒長
  private Request buildRequestRecursive( 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 mainRequest =
        buildThumbnailRequestRecursive(
            target,
            targetListener,
            parentCoordinator,
            transitionOptions,
            priority,
            overrideWidth,
            overrideHeight,
            requestOptions,
            callbackExecutor);

    if (errorRequestCoordinator == null) {
      return mainRequest;
    }

    ...
        //若是有設置錯誤時的處理邏輯
    return errorRequestCoordinator;
  }
複製代碼

能夠看到,真正的核心代碼在buildThumbnailRequestRecursive方法

//這個方法結構其實很簡單,可是參數太多,因此把參數省略再看
    private Request buildThumbnailRequestRecursive( ...) {
        //默認的thumbnailBuilder就是空的,除非手動調用RequestBuilder類的thumbnail方法
        //不然這個if代碼塊永遠執行不到
        if (thumbnailBuilder != null) {
            // Recursive case: contains a potentially recursive thumbnail request builder.
            if (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()");
            }

            TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions =
                thumbnailBuilder.transitionOptions;

            // Apply our transition by default to thumbnail requests but avoid overriding custom options
            // that may have been applied on the thumbnail request explicitly.
            if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
                thumbTransitionOptions = transitionOptions;
            }

            //縮略圖權限
            Priority thumbPriority = thumbnailBuilder.isPrioritySet()
                ? thumbnailBuilder.getPriority() : getThumbnailPriority(priority);

            //縮略圖寬高
            int thumbOverrideWidth = thumbnailBuilder.getOverrideWidth();
            int thumbOverrideHeight = thumbnailBuilder.getOverrideHeight();
            //寬高檢驗
            if (Util.isValidDimensions(overrideWidth, overrideHeight)
                && !thumbnailBuilder.isValidOverride()) {
                thumbOverrideWidth = requestOptions.getOverrideWidth();
                thumbOverrideHeight = requestOptions.getOverrideHeight();
            }

            //縮略圖請求協議器,同時協調原圖與縮略圖的request
            ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
            //原圖請求
            Request fullRequest =
                obtainRequest(...);
            isThumbnailBuilt = true;
            // Recursively generate thumbnail requests.
            //調用buildRequestRecursive,仍是會調到buildThumbnailRequestRecursive,這是個遞歸方法
            //遞歸生成縮略圖請求
            Request thumbRequest =
                thumbnailBuilder.buildRequestRecursive(...);
            isThumbnailBuilt = false;
            //把這兩個request包裝到ThumbnailRequestCoordinator中
            coordinator.setRequests(fullRequest, thumbRequest);
            return coordinator;
        } else if (thumbSizeMultiplier != null) {
            //根據指定的縮放係數加載縮略圖
            // Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
            ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
            Request fullRequest =
                obtainRequest(...);
            BaseRequestOptions<?> thumbnailOptions =
                requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);

            Request thumbnailRequest =
                obtainRequest(...);

            coordinator.setRequests(fullRequest, thumbnailRequest);
            return coordinator;
        } else {
            //只加載原圖
            // Base case: no thumbnail.
            return obtainRequest(...);
        }
    }
複製代碼

能夠看到,在buildThumbnailRequestRecursive主要作了有無縮略圖的判斷,而後再進行加載,最後調用了obtainRequest方法

private Request obtainRequest( Target<TranscodeType> target, RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> requestOptions, RequestCoordinator requestCoordinator, TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority, int overrideWidth, int overrideHeight, Executor callbackExecutor) {
    return SingleRequest.obtain(
        context,
        glideContext,
        model,//對應load(url),好比一個圖片地址
        transcodeClass,
        requestOptions,
        overrideWidth,//寬
        overrideHeight,//高
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        glideContext.getEngine(),//全局加載引擎
        transitionOptions.getTransitionFactory(),
        callbackExecutor);
  }
複製代碼

這個方法經過SingleReques類的方法obtain去建立一個Request對象,因此,它就是咱們要找的requst,那麼看它的begin方法

開啓資源加載任務
@Override
  public synchronized void begin() {
    assertNotCallingCallbacks();
    stateVerifier.throwIfRecycled();
    startTime = LogTime.getLogTime();
      //若是圖片的來源沒有設置,加載失敗
    if (model == null) {
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        width = overrideWidth;
        height = overrideHeight;
      }
      // Only log at more verbose log levels if the user has set a fallback drawable, because
      // fallback Drawables indicate the user expects null models occasionally.
      int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
      onLoadFailed(new GlideException("Received null model"), logLevel);
      return;
    }

    if (status == Status.RUNNING) {
      throw new IllegalArgumentException("Cannot restart a running request");
    }

    // If we're restarted after we're complete (usually via something like a notifyDataSetChanged
    // that starts an identical request into the same Target or View), we can simply use the
    // resource and size we retrieved the last time around and skip obtaining a new size, starting a
    // new load etc. This does mean that users who want to restart a load because they expect that
    // the view size has changed will need to explicitly clear the View or Target before starting
    // the new load.
    if (status == Status.COMPLETE) {
      onResourceReady(resource, DataSource.MEMORY_CACHE);
      return;
    }

    // Restarts for requests that are neither complete nor running can be treated as new requests
    // and can run again from the beginning.

    status = Status.WAITING_FOR_SIZE;
      //若是Target的寬高已經獲取併合法,就開始下一步
    if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
      onSizeReady(overrideWidth, overrideHeight);
    } else {
        //手動獲取寬高
      target.getSize(this);
    }

    if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
        && canNotifyStatusChanged()) {
        //設置佔位圖
      target.onLoadStarted(getPlaceholderDrawable());
    }
    if (IS_VERBOSE_LOGGABLE) {
      logV("finished run method in " + LogTime.getElapsedMillis(startTime));
    }
  }

複製代碼

能夠看到,begin方法通過一系列的判斷,當status是RUNNING或者WAITING_FOR_SIZE狀態,而且須要設置佔位圖時,會調用onLoadStarted設置佔位圖,當狀態是COMPLETE時,會執行onResourceReady方法並返回。

@Override
  public synchronized void onResourceReady(Resource<?> resource, DataSource dataSource) {
    stateVerifier.throwIfRecycled();
    loadStatus = null;
    ...
	//判斷是否須要設置資源,若是不須要就直接釋放並設置狀態爲COMPLETE
    if (!canSetResource()) {
      releaseResource(resource);
      // We can't put the status to complete before asking canSetResource().
      status = Status.COMPLETE;
      return;
    }

      //執行方法
    onResourceReady((Resource<R>) resource, (R) received, dataSource);
  }
複製代碼

上面省略了一大段加載失敗的代碼,直接來看onResourceReady的重載方法。

private synchronized void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
    // We must call isFirstReadyResource before setting status.
    boolean isFirstResource = isFirstReadyResource();
    status = Status.COMPLETE;
    this.resource = resource;
    ...
    try {
      boolean anyListenerHandledUpdatingTarget = false;
      if (requestListeners != null) {
        for (RequestListener<R> listener : requestListeners) {
          anyListenerHandledUpdatingTarget |=
              listener.onResourceReady(result, model, target, dataSource, isFirstResource);
        }
      }
      anyListenerHandledUpdatingTarget |=
          targetListener != null
              && targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);
		
      //設置資源及動畫相關的信息
      if (!anyListenerHandledUpdatingTarget) {
        Transition<? super R> animation =
            animationFactory.build(dataSource, isFirstResource);
          //這個target有多個,好比DrawableImageViewTarget 
        target.onResourceReady(result, animation);
      }
    } finally {
      isCallingCallbacks = false;
    }

      //最後通知加載成功
    notifyLoadSuccess();
  }
複製代碼

能夠看到,當狀態爲COMPLETE時,就是把當前result設置到當前的target上,並通知加載成功(作一些加載成功後的清理工做)。

上面是COMPLETE時的狀態,那麼不是這個狀態時呢?會執行到onSizeReady方法

@Override
  public synchronized void onSizeReady(int width, int height) {
    stateVerifier.throwIfRecycled();
    ...
    status = Status.RUNNING;

      //計算縮略圖的尺寸
    float sizeMultiplier = requestOptions.getSizeMultiplier();
    this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
    this.height = maybeApplySizeMultiplier(height, sizeMultiplier);

    if (IS_VERBOSE_LOGGABLE) {
      logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
    }
      //加載流程
    loadStatus =
        engine.load(
            glideContext,
            model,//對應rul,圖片地址
            requestOptions.getSignature(),
            this.width,
            this.height,
            requestOptions.getResourceClass(),//默認是Object.class
            transcodeClass,//默認是Drawable.class
            priority,
            requestOptions.getDiskCacheStrategy(),//緩存策略,默認是AUTOMATIC
            requestOptions.getTransformations(),
            requestOptions.isTransformationRequired(),
            requestOptions.isScaleOnlyOrNoTransform(),
            requestOptions.getOptions(),
            requestOptions.isMemoryCacheable(),
            requestOptions.getUseUnlimitedSourceGeneratorsPool(),
            requestOptions.getUseAnimationPool(),
            requestOptions.getOnlyRetrieveFromCache(),
            this,
            callbackExecutor);
  }
複製代碼

能夠看到,調用了Engine的load方法,關於加載圖片的加載機制,咱們下一篇再講,今天先就講到這。

總結

這一篇主要分析Glide.with().load().into()的簡單流程

Glide流程

  1. Glide類做爲入口類,調用靜態方法with(),實例化了Glide這個單例,取得RequestManager對象並返回
  2. RequestManager去管理Request請求,根據Activity或Fragment生命週期,管理request請求,包括:onStop,onStart,onDestory,pauseRequest,resumeRequests等,並能夠設置加載資源要返回的資源類型,Bitmap,Drawable,Gif。經過調用load()、asBitmap()、asFile()等方法均返回一個RquestBuilder對象,將資源的請求處理移交給了RequestBuilder,實現將功能分離,模塊化處理。
  3. RquestBuilder處理資源加載請求,調用apply()方法傳入RequestOptions對象進行一些選項設置;調用transition()方法實現資源加載顯示時過分動畫;最後調用into()方法,去構建Rquest對象或使用Target設置過的Request對象,調用Rquest的對象方法begin()開啓加載請求。
  4. 開啓請求後的工做就移交到Request類中,加載完成後,Request調用onResourceReady()方法去判斷加載結果,若加載成功,調用Target類的onReadySuccess()方法設置資源,調用RequestCoordinator中方法onRequestSuccess()執行加載成功後的資源清理工做。若加載失敗,Request直接調用notifyLoadFailed()方法,將清理資源工做移交給RequestCoordinator類處理。

參考


個人CSDN

下面是個人公衆號,歡迎你們關注我

相關文章
相關標籤/搜索