Glide v4 源碼淺析(1)-with


簡述

Glide爲Android平臺下的圖片加載框架,它的使用方法可以查看教程文檔

這裏從一個最簡單的使用實例入手,分析glide源碼調用過程(使用的glide版本爲v4.8.0):

Glide.with(activity)
     .load(imgUrl)
     .into(imageView);

本例實現了在一個FragmentActivity中,加載遠程圖片,顯示在imageview視圖上。圖片加載過程大致可以分爲三步:

  • with: 預備開啓一個加載,並與當前Activity生命週期綁定;
  • load:設置數據源,構建請求的參數;
  • into:創建請求,開始真正的加載圖片,最終顯示在視圖上。

接下來從第一步with方法開始,看看源碼中做了什麼操作。

源碼分析

with方法中主要做了兩件事,一是初始化Glide對象,二是返回合適的RequestManager對象。

Glide初始化

在Glide類中,有多個with方法的重載實現,最終都是返回RequestManager對象,(RequestManager負責管理髮起的加載Request),如圖:

簡單概括它們的作用是當傳入的上下文爲FragmentActivity或者可以取到FragmentActivity時,可以將本次加載與FragmentActivity的生命週期進行綁定,其中又分別適配了v4和app的FragmentManager。

在本例中將會調用下面的重載方法:

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

其中getRetriever方法返回RequestManagerRetriever(顧名思義,它負責創建或檢索出合適的RequestManager)。

@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
  // Context could be null for other reasons (ie the user passes in null), but in practice it will
  // only occur due to errors with the Fragment lifecycle.
  Preconditions.checkNotNull(
      context,
      "You cannot start a load on a not yet attached View or a Fragment where getActivity() "
          + "returns null (which usually occurs when getActivity() is called before the Fragment "
          + "is attached or after the Fragment is destroyed).");
  return Glide.get(context).getRequestManagerRetriever();
}

看Glide.get(context)方法,返回單例:

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

  return glide;
}

checkAndInitializeGlide方法中加了一個boolean變量判斷避免重複調用初始化,其中又調用initializeGlide方法。

接下來就是Glide的初始化過程

private static void initializeGlide(@NonNull Context context) {
  initializeGlide(context, new GlideBuilder());
}

@SuppressWarnings("deprecation")
privatestatic void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
  Context applicationContext = context.getApplicationContext();
  // 獲取註解生成的自定義的GlideModule,具體使用查看Glide文檔「Generated API」說明。
  GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
  List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
  if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
    // 獲取在AndroidManifest中註冊的GlideModule(Glide V4之前的版本使用)。
    manifestModules = new ManifestParser(applicationContext).parse();
  }

  if (annotationGeneratedModule != null
      && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
    Set<Class<?>> excludedModuleClasses =
        annotationGeneratedModule.getExcludedModuleClasses();
    Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();
    while (iterator.hasNext()) {
      // 排除不需要的GlideModule(由自己決定)。
      com.bumptech.glide.module.GlideModule current = iterator.next();
      if (!excludedModuleClasses.contains(current.getClass())) {
        continue;
      }
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
      }
      iterator.remove();
    }
  }

  if (Log.isLoggable(TAG, Log.DEBUG)) {
    for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {
      Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
    }
  }

  // 獲取自定義的RequestManagerFactory,設置給GlideBuilder。
  RequestManagerRetriever.RequestManagerFactory factory =
      annotationGeneratedModule != null
          ? annotationGeneratedModule.getRequestManagerFactory() : null;
  builder.setRequestManagerFactory(factory);
  for (com.bumptech.glide.module.GlideModule module : manifestModules) {
    // 可以在自定義的GlideModule中給GlideBuilder設置配置。
    module.applyOptions(applicationContext, builder);
  }
  if (annotationGeneratedModule != null) {
    // 可以在自定義的GlideModule中給GlideBuilder設置配置。
    annotationGeneratedModule.applyOptions(applicationContext, builder);
  }
  // 通過GlideBuilder構造了一個Glide對象。
  Glide glide = builder.build(applicationContext);
  for (com.bumptech.glide.module.GlideModule module : manifestModules) {
    // 可以在自定義的GlideModule中給glide中的Registry添加或替換組件。
    module.registerComponents(applicationContext, glide, glide.registry);
  }
  if (annotationGeneratedModule != null) {
    // 可以在自定義的GlideModule中給glide中的Registry添加或替換組件。
    annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
  }
  // 註冊ComponentCallbacks2用以監聽內存使用情況。
  applicationContext.registerComponentCallbacks(glide);
  Glide.glide = glide;
}

在本例中使用默認的glide配置,沒有自定義GlideModule,直接看builder.build(applicationContext)方法:

@NonNull
Glide build(@NonNull Context context) {
  // 初始化用於網絡操作的線程池。
  if (sourceExecutor == null) {
    sourceExecutor = GlideExecutor.newSourceExecutor();
  }

  // 初始化用於磁盤緩存操作的線程池
  if (diskCacheExecutor == null) {
    diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
  }

  // 初始化用於動畫的線程池
  if (animationExecutor == null) {
    animationExecutor = GlideExecutor.newAnimationExecutor();
  }

  // 初始化根據手機設備推薦緩存容器大小的計算輔助工具類
  if (memorySizeCalculator == null) {
    memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
  }

  // 初始化生成網絡監聽廣播註冊的工廠類,該Factory會根據是否有NETWORK_PERMISSION生成對應的監聽器(通常情況下都應該申請)。擁有權限情況下的監聽器會註冊廣播監聽CONNECTIVITY_ACTION,當收到聯網廣播時會觸發RequestManager嘗試重試請求。
  if (connectivityMonitorFactory == null) {
    connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
  }

  // 初始化bitmap緩存容器
  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());
  }

  // 初始化Resource緩存容器
  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(),
            GlideExecutor.newAnimationExecutor(),
            isActiveResourceRetentionAllowed);
  }

  // 初始化獲取RequestManager的工具類,接下來馬上就會用到。
  RequestManagerRetriever requestManagerRetriever =
      new RequestManagerRetriever(requestManagerFactory);

  // 最終創建並返回Glide對象
  return new Glide(
      context,
      engine,
      memoryCache,
      bitmapPool,
      arrayPool,
      requestManagerRetriever,
      connectivityMonitorFactory,
      logLevel,
      defaultRequestOptions.lock(),
      defaultTransitionOptions);
}

GlideBuilder的build方法中初始化了多個線程池對應不同使用功能,便於不同模塊的線程管理,以及緩存容器和Engine、RequestManagerRetriever對象。之後實例化Glide對象並傳入各個參數。

接着看Glide的構造方法:

Glide(
   @NonNull Context context,
   @NonNull Engine engine,
   @NonNull MemoryCache memoryCache,
   @NonNull BitmapPool bitmapPool,
   @NonNull ArrayPool arrayPool,
   @NonNull RequestManagerRetriever requestManagerRetriever,
   @NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
   int logLevel,
   @NonNull RequestOptions defaultRequestOptions,
   @NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions) {
 this.engine = engine;
 this.bitmapPool = bitmapPool;
 this.arrayPool = arrayPool;
 this.memoryCache = memoryCache;
 this.requestManagerRetriever = requestManagerRetriever;
 this.connectivityMonitorFactory = connectivityMonitorFactory;

 DecodeFormat decodeFormat = defaultRequestOptions.getOptions().get(Downsampler.DECODE_FORMAT);
 bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);
 
 final Resources resources = context.getResources();   
 
 registry = new Registry();
 // Right now we're only using this parser for HEIF images, which are only supported on OMR1+.
 // If we need this for other file types, we should consider removing this restriction.
 // Note that order here matters. We want to check the ExifInterface parser first for orientation
 // and then fall back to DefaultImageHeaderParser for other fields.
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
   registry.register(new ExifInterfaceImageHeaderParser());
 }
 registry.register(new DefaultImageHeaderParser());
 
 ···
 
 registry
     .append(ByteBuffer.class, new ByteBufferEncoder())
     ···
     .append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder)
     ···
     .append(Bitmap.class, Bitmap.class, UnitModelLoader.Factory.<Bitmap>getInstance())
     .append(
         Registry.BUCKET_BITMAP, Bitmap.class, Bitmap.class, new UnitBitmapDecoder())
     .append(Bitmap.class, bitmapEncoder)
     ···
     .register(new ByteBufferRewinder.Factory())
     ···
     .register(
         Bitmap.class,
         BitmapDrawable.class,
         new BitmapDrawableTranscoder(resources))
     ···
     ;

 ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
 glideContext =
     new GlideContext(
         context,
         arrayPool,
         registry,
         imageViewTargetFactory,
         defaultRequestOptions,
         defaultTransitionOptions,
         engine,
         logLevel);
}

這裏主要做了三件事:
1.保存在GlideBuilder中完成初始化的對象;
2.初始化Registry對象,該對象中註冊了一系列資源轉換和編解碼的工具類,後續流程會從中查找對應的工具類去解析和處理資源;
3.初始化GlideContext對象,該對象繼承自ContextWrapper,後續的流程中會通過它獲取註冊表和引擎等加載資源所需的對象。

以上完成了Glide對象的創建和初始化。回到Glide的getRetriever方法中,這裏將返回RequestManagerRetriever對象,接下來是通過它獲取RequestManager對象。

RequestManager獲取

RequestManagerRetriever類的get方法也有多個重載:

with方法需要多個重載主要是因爲這裏,這裏根據參數類型查找FragmentManager,利用它實現和當前activity的生命週期綁定。

先看get(Context):

@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)) {
    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);
}

根據context的類型再調用相應的get方法。若當前非主線程或上下文是Application,直接調用getApplicationManager方法(這種情況下不會綁定生命週期)。

不進行生命週期綁定的RequestManager

當在子線程調用with方法,或傳入上下文爲application時,會通過getApplicationManager方法返回RequestManager對象:

@NonNull
private RequestManager getApplicationManager(@NonNull Context context) {
  // Either an application context or we're on a background thread.
  if (applicationManager == null) {
    synchronized (this) {
      if (applicationManager == null) {
        // Normally pause/resume is taken care of by the fragment we add to the fragment or
        // activity. However, in this case since the manager attached to the application will not
        // receive lifecycle events, we must force the manager to start resumed using
        // ApplicationLifecycle.

        // TODO(b/27524013): Factor out this Glide.get() call.
        Glide glide = Glide.get(context.getApplicationContext());
        applicationManager =
            factory.build(
                glide,
                // ApplicationLifecycle實現Lifecycle接口,用於跟蹤和通知Application的生命週期事件。
                new ApplicationLifecycle(),
                new EmptyRequestManagerTreeNode(),
                context.getApplicationContext());
      }
    }
  }

  return applicationManager;
}

該方法會返回一個單例的RequestManager對象,通過工廠模式創建,factory在RequestManagerRetriever實例化時候賦值,默認爲DEFAULT_FACTORY:

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);
  }
};

可以看到build方法直接new了一個RequestManager對象,接着看看RequestManager的構造方法:

public RequestManager(
    @NonNull Glide glide, @NonNull Lifecycle lifecycle,
    @NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
  this(
      glide,
      lifecycle,
      treeNode,
      new RequestTracker(),
      glide.getConnectivityMonitorFactory(),
      context);
}

// Our usage is safe here.
@SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
RequestManager(
    Glide glide,
    Lifecycle lifecycle,
    RequestManagerTreeNode treeNode,
    RequestTracker requestTracker,
    ConnectivityMonitorFactory factory,
    Context context) {
  this.glide = glide;
  this.lifecycle = lifecycle;
  this.treeNode = treeNode;
  // requestTracker用於跟蹤、取消和重新啓動進行中、已完成和失敗的請求。
  this.requestTracker = requestTracker;
  this.context = context;
  
  // 創建網絡連接監聽器,當網絡恢復可用時會通過requestTracker嘗試重啓請求。
  connectivityMonitor =
      factory.build(
          context.getApplicationContext(),
          new RequestManagerConnectivityListener(requestTracker));

  // If we're the application level request manager, we may be created on a background thread.
  // In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
  // issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
  // This should be entirely safe.
  // 在主線程添加LifecycleListener到Lifecycle中
  if (Util.isOnBackgroundThread()) {
    mainHandler.post(addSelfToLifecycle);
  } else {
    lifecycle.addListener(this);
  }
  lifecycle.addListener(connectivityMonitor);
  
  setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());

  // 將自身保存到glide的managers成員變量中(managers爲一個ArrayList)。
  glide.registerRequestManager(this);
}

這裏的lifecycle爲ApplicationLifecycle,它的addListener方法只是通知新的監聽器已啓動。

與當前Activity進行生命週期綁定的RequestManager

get的其他重載方法都是試圖獲取到FragmentManager,然後調用supportFragmentGet方法或者fragmentGet方法查找或創建RequestManager對象。
(ps:fragmentGet方法適配android.app.FragmentManager,已棄用)

這裏以get(FragmentActivity)爲例:

@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
  if (Util.isOnBackgroundThread()) {
    return get(activity.getApplicationContext());
  } else {
    assertNotDestroyed(activity);
    // 獲取FragmentManager
    FragmentManager fm = activity.getSupportFragmentManager();
    return supportFragmentGet(
        activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
  }
}

關鍵在supportFragmentGet方法:

@NonNull
private RequestManager supportFragmentGet(
    @NonNull Context context,
    @NonNull FragmentManager fm,
    @Nullable Fragment parentHint,
    boolean isParentVisible) {
  // 查找SupportRequestManagerFragment對象,它就是一個Fragment
  SupportRequestManagerFragment current =
      getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
  // 從SupportRequestManagerFragment中獲取requestManager  
  RequestManager requestManager = current.getRequestManager();
  // 若不存在則創建,之後保存在SupportRequestManagerFragment中
  if (requestManager == null) {
    // TODO(b/27524013): Factor out this Glide.get() call.
    Glide glide = Glide.get(context);
    // 這裏創建RequestManager時傳入了ActivityFragmentLifecycle
    requestManager =
        factory.build(
            glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
    current.setRequestManager(requestManager);
  }
  return requestManager;
}

該方法中會通過getSupportRequestManagerFragment方法獲取一個Fragment,返回其中的RequestManager,若不存在則新建一個,並保存在Fragment中。

接着看getSupportRequestManagerFragment方法:

@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(
    @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
  // 通過tag查找當前頁面中的指定Fragment
  SupportRequestManagerFragment current =
      (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
  if (current == null) {
    // 獲取已創建但等待往當前頁面添加的Fragment,避免fm add fragment期間重複創建
    current = pendingSupportRequestManagerFragments.get(fm);
    if (current == null) {
      // 初始化SupportRequestManagerFragment
      current = new SupportRequestManagerFragment();
      current.setParentFragmentHint(parentHint);
      if (isParentVisible) {
        current.getGlideLifecycle().onStart();
      }
      // 保存到集合中避免重複創建
      pendingSupportRequestManagerFragments.put(fm, current);
      // 將SupportRequestManagerFragment添加到當前頁面中
      fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
      // 在handler的handleMessage中會將上面保存的從集合中移除
      handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
    }
  }
  return current;
}

這裏可以看出,Glide是通過往當前頁面添加一個Fragment,藉助Fragment的生命週期來通知RequestManager,來實現綁定管理。

SupportRequestManagerFragment和RequestManager之間是通過ActivityFragmentLifecycle來實現生命週期回調:

public SupportRequestManagerFragment() {
  this(new ActivityFragmentLifecycle());
}

@VisibleForTesting
@SuppressLint("ValidFragment")
public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
  this.lifecycle = lifecycle;
}

在supportFragmentGet方法中創建RequestManager時,會傳入SupportRequestManagerFragment的lifecycle成員變量:

requestManager =
    factory.build(
        glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);

而在RequestManager的構造方法中,又會向這個lifecycle中註冊LifecycleListener接口的實現類即RequestManager自身:

if (Util.isOnBackgroundThread()) {
  // 發送到主線程添加
  mainHandler.post(addSelfToLifecycle);
} else {
  // 添加自身,RequestManager實現了LifecycleListener接口
  lifecycle.addListener(this);
}
// 添加網絡監聽器
lifecycle.addListener(connectivityMonitor);

因此實現了綁定關係:

@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();
}

在Fragment的生命週期回調方法中調用lifecycle的對應方法,而lifecycle中又會調用LifecycleListener接口的相應方法,即RequestManager的onStart、onStop、onDestroy方法。

總結

Glide的with方法會初始化Glide單例對象,並完成一系列默認和自定義配置。之後通過它的requestManagerRetriever成員變量查找創建返回RequestManager對象,後續會通過這個RequestManager進行資源請求的管理。在獲取RequestManager的過程中,會通過往當前頁面添加一個Fragment,來實現RequestManager和頁面生命週期綁定。

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