Glide系列 -- 與Activity關(guān)聯(lián)關(guān)系

分析版本為glide:4.9.0

時序圖


Glide與Activity生命周期相關(guān)聯(lián)

with方法

  • with(Context context)
  • with(Activity activity)
  • with(FragmentActivity activity)
  • with(android.app.Fragment fragment)
  • with(Fragment fragment)// v4包下
  • with(View view)

所有這些with方法,首先都會根據(jù)傳入的值獲取到ApplicationContext,生成Glide對象悔雹,并獲取RequestManagerRetriever對象

根據(jù)代碼分析下

首先得到Glide對象 --initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder)方法

 @SuppressWarnings("deprecation")
  private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
    // with方法根據(jù)不同的傳值獲取其上下文 獲取到全局的上下文
    Context applicationContext = context.getApplicationContext();
    // 獲取注解GlideModule的類 如果沒有自定義的GlideModule則表蝙,返回null
    GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
    List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
    // 獲取AndroidManifest.xml中meta-data中配置的GlideModule
    if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
      manifestModules = new ManifestParser(applicationContext).parse();
    }
    // 刪除manifestModules中與注解GlideModule重復(fù)的module
    if (annotationGeneratedModule != null
        && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
      Set<Class<?>> excludedModuleClasses =
          annotationGeneratedModule.getExcludedModuleClasses();
      Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();
      while (iterator.hasNext()) {
        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();
      }
    }
    ... // 輸出log,無關(guān)代碼
    // 獲取RequestManagerFactory對象 如果沒有自定義的GlideModule則為null
    RequestManagerRetriever.RequestManagerFactory factory =
        annotationGeneratedModule != null
            ? annotationGeneratedModule.getRequestManagerFactory() : null;
    builder.setRequestManagerFactory(factory);
    for (com.bumptech.glide.module.GlideModule module : manifestModules) {
      module.applyOptions(applicationContext, builder);
    }
    if (annotationGeneratedModule != null) {
      annotationGeneratedModule.applyOptions(applicationContext, builder);
    }
    // 生成Glide對象
    Glide glide = builder.build(applicationContext);
    for (com.bumptech.glide.module.GlideModule module : manifestModules) {
      module.registerComponents(applicationContext, glide, glide.registry);
    }
    if (annotationGeneratedModule != null) {
      annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
    }
    applicationContext.registerComponentCallbacks(glide);
    Glide.glide = glide;
  }

第二步一屋,獲取RequestManagerRetriever對象
這步很簡單逢享,我們在生成Glide對象的時候就已經(jīng)生成的RequestManagerRetriever對象
GlideBuilder的build方法

...
// 根據(jù)上面分析芙扎,我們?nèi)绻麤]有寫自定義GlideModule方法,requestManagerFactory為null
 RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);
 return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptions.lock(),
        defaultTransitionOptions,
        defaultRequestListeners,
        isLoggingRequestOriginsEnabled);
  }

RequestManagerRetriever.java

public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
    // 如果factory為空,使用默認(rèn)的RequestManagerFactory
    this.factory = factory != null ? factory : DEFAULT_FACTORY;
    // 此處愧薛,我覺得很重要
    handler = new Handler(Looper.getMainLooper(), this /* Callback */);
  }

第三步,獲取RequestManager對象

根據(jù)我們調(diào)用with方法傳入的對象獲取RequestManager對象

如果當(dāng)前是后臺線程诊赊,直接獲取ApplicationContext處理

我們先來分析在當(dāng)前UI線程

 @NonNull
  public RequestManager get(@NonNull Activity activity) {
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      android.app.FragmentManager fm = activity.getFragmentManager();
      return fragmentGet(
          activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }
@Deprecated
  @NonNull
  private RequestManager fragmentGet(@NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
      // 獲取RequestManagerFragment
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
    // 獲取fragment中的requestManager
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      // TODO(b/27524013): Factor out this Glide.get() call.
      Glide glide = Glide.get(context);
      // 如果沒有厚满,則新建一個,并設(shè)置到fragment中
      // factory 如果我們沒有自定的module設(shè)置的話碧磅,使用的是默認(rèn)的factory
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

獲取RequestManagerFragment

 @NonNull
  private RequestManagerFragment getRequestManagerFragment(
      @NonNull final android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
      // 先從FragmentManager中找看是否已經(jīng)存在該fragment
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null)
    // 如果沒有碘箍,則從我們自己的Map中找
      current = pendingRequestManagerFragments.get(fm);
      if (current == null) {
        // 如果都沒有,則新建一個fragment 
        current = new RequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        // 如果當(dāng)前Activity沒有isFinishing則isParentVisible為true
        if (isParentVisible) {
            // 觸發(fā)lifecycle的onStart方法
          current.getGlideLifecycle().onStart();
        }
        //放入自己的map中
        pendingRequestManagerFragments.put(fm, current);
        // 開啟事物鲸郊,加tag 顯示fragment
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

獲取requestManager對象 最終調(diào)用RequestManager的構(gòu)造方法

RequestManager(
      Glide glide,
      Lifecycle lifecycle,
      RequestManagerTreeNode treeNode,
      RequestTracker requestTracker,
      ConnectivityMonitorFactory factory,
      Context context) {
    this.glide = glide;
    // lifecycle 為fragment中的ActivityFragmenLifecycle對象
    this.lifecycle = lifecycle;
    this.treeNode = treeNode;
    // 請求追蹤器  requestTracker = new RequestTracker()
    this.requestTracker = requestTracker;
    this.context = context;
    // 連接的監(jiān)聽器
    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.
    if (Util.isOnBackgroundThread()) {
      mainHandler.post(addSelfToLifecycle);
    } else {
        // 如果不是后臺線程丰榴,則添加listener
      lifecycle.addListener(this);
    }
    // 添加連接監(jiān)聽器
    lifecycle.addListener(connectivityMonitor);

    defaultRequestListeners =
        new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
    setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
    
    // 把requestManager注冊到glide中
    glide.registerRequestManager(this);
  }

當(dāng)我們所在的Activity執(zhí)行onStop()方法之后,所關(guān)聯(lián)的fragment也會執(zhí)行onStop()方法

RequestManagerFragment.java

public void onStop() {
    super.onStop();
    // lifecycle為ActivityFragmentLifecycle
    lifecycle.onStop();
  }

ActivityFragmentLifecycle.java

void onStop() {
    isStarted = false;
    //迭代注冊的listener 執(zhí)行onStop方法
    // 一個listener為RequestManager
    // 一個為connectivityMonitor
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStop();
    }
  }

RequestManager.java

public synchronized void onStop() {
    pauseRequests();
    targetTracker.onStop();
  }
  
  public synchronized void pauseRequests() {
    // requestTracker 為RequestTracker對象 在RequestManager構(gòu)造函數(shù)中創(chuàng)建
    requestTracker.pauseRequests();
  }

RequestTracker.java

/**
   * Stops any in progress requests. 停止任何正在進(jìn)行的請求
   */
public void pauseRequests() {
    isPaused = true;
    for (Request request : Util.getSnapshot(requests)) {
      if (request.isRunning()) {
        request.clear();
        // 將請求加入list
        pendingRequests.add(request);
      }
    }
  }

到此秆撮,頁面onStop后四濒,Glide不在加載

同理 頁面onStart()恢復(fù)之后
RequestTracker.java

/**
   * Starts any not yet completed or failed requests. 
   * 開始沒有完成或者失敗的請求
   */
  public void resumeRequests() {
    isPaused = false;
    for (Request request : Util.getSnapshot(requests)) {
      // We don't need to check for cleared here. Any explicit clear by a user will remove the
      // Request from the tracker, so the only way we'd find a cleared request here is if we cleared
      // it. As a result it should be safe for us to resume cleared requests.
      if (!request.isComplete() && !request.isRunning()) {
        request.begin();
      }
    }
    // 清空列表
    pendingRequests.clear();
  }

onDestory()

/**
   * Lifecycle callback that cancels all in progress requests and clears and recycles resources for
   * all completed requests.
   * 清空所有的請求,glide與RequestManager解除關(guān)系
   */
  @Override
  public synchronized void onDestroy() {
    targetTracker.onDestroy();
    for (Target<?> target : targetTracker.getAll()) {
      clear(target);
    }
    targetTracker.clear();
    requestTracker.clearRequests();
    lifecycle.removeListener(this);
    lifecycle.removeListener(connectivityMonitor);
    mainHandler.removeCallbacks(addSelfToLifecycle);
    glide.unregisterRequestManager(this);
  }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末职辨,一起剝皮案震驚了整個濱河市盗蟆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌舒裤,老刑警劉巖喳资,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異腾供,居然都是意外死亡仆邓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門伴鳖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來节值,“玉大人,你說我怎么就攤上這事榜聂「懔疲” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵须肆,是天一觀的道長贴汪。 經(jīng)常有香客問我,道長休吠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任业簿,我火速辦了婚禮瘤礁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梅尤。我一直安慰自己柜思,他們只是感情好岩调,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著赡盘,像睡著了一般号枕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上陨享,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天葱淳,我揣著相機(jī)與錄音,去河邊找鬼抛姑。 笑死赞厕,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的定硝。 我是一名探鬼主播皿桑,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蔬啡!你這毒婦竟也來了诲侮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤箱蟆,失蹤者是張志新(化名)和其女友劉穎沟绪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顽腾,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡近零,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了抄肖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片久信。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖漓摩,靈堂內(nèi)的尸體忽然破棺而出裙士,到底是詐尸還是另有隱情,我是刑警寧澤管毙,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布腿椎,位于F島的核電站,受9級特大地震影響夭咬,放射性物質(zhì)發(fā)生泄漏啃炸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一卓舵、第九天 我趴在偏房一處隱蔽的房頂上張望南用。 院中可真熱鬧,春花似錦、人聲如沸裹虫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽筑公。三九已至雳窟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間匣屡,已是汗流浹背封救。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留耸采,地道東北人兴泥。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像虾宇,于是被迫代替她去往敵國和親搓彻。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353