Glide4.9圖片框架源碼(二)之如何綁定Activity的生命周期

上一節(jié)我們簡(jiǎn)單的介紹了Glide的常規(guī)使用方法,有需要的話(huà)可以看看上一節(jié):

Glide框架之加載圖片的常規(guī)使用方式

Glide.with(this).load(url).into(imageView)

標(biāo)題這一句代碼,囊括了整個(gè)Glide的核心功能,可以說(shuō)Glide在這一行代碼中做了成噸的工作,最繁重的任務(wù)是在into方法中,但是我們根據(jù)順序,首先看一下with方法。說(shuō)到Glide源碼,面試中大家可能都知道Glide為何能監(jiān)聽(tīng)頁(yè)面或者application的生命周期,從而及時(shí)的取消請(qǐng)求和回收對(duì)象,是通過(guò)綁定一個(gè)空的fragment。那么我們就來(lái)看一下,with方法中,是如何實(shí)現(xiàn)這個(gè)操作的。

Glide.with(this)方法

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

    /** @deprecated */
    @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);
    }

glide提供的with方法比較多,其實(shí)這里看的出來(lái),不管是傳入context還是activity亦或是fragment,其實(shí)還是拿到當(dāng)前頁(yè)面所屬的context,那么這里是情況其實(shí)只有兩種,一種是普通的context,另一種這是applicationcontext。我們以傳入context為例,調(diào)用的是return getRetriever(context).get(context),返回值則是一個(gè)RequestManager,我們跟進(jìn)去看看getRetriever(context)方法:

    @NonNull
    private static RequestManagerRetriever getRetriever(@Nullable Context context) {
        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 get(context).getRequestManagerRetriever();
    }

checkNotNull方法執(zhí)行的是context的空檢查,我們繼續(xù)看一下get(context).getRequestManagerRetriever()中的get(context)

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

這里get方法是獲取glide實(shí)例,實(shí)現(xiàn)的一個(gè)單例方法,其中checkAndInitializeGlide對(duì)glide進(jìn)行初始化,這里我們不去細(xì)究回到上一步繼續(xù)看看get(context).getRequestManagerRetriever()的getRequestManagerRetriever()方法

    @NonNull
    public RequestManagerRetriever getRequestManagerRetriever() {
        return this.requestManagerRetriever;
    }

這里直接返回的是RequestManagerRetriever,那么這個(gè)變量是什么時(shí)候初始化的呢,我們看下Glide的build方法發(fā)現(xiàn)這里初始化了RequestManagerRetriever。到這里with方法中的getRetriever(context).get(context)的getRetriever結(jié)束,我們繼續(xù)看看get(context),這里應(yīng)該返回了一個(gè)RequestManagerRetriever里面的RequestManager,來(lái)看下源碼:

 @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 this.get((FragmentActivity)context);
                }
                if (context instanceof Activity) {
                    return this.get((Activity)context);
                }
                if (context instanceof ContextWrapper) {
                    return this.get(((ContextWrapper)context).getBaseContext());
                }
            }
            return this.getApplicationManager(context);
        }
    }

這里看出將context分成了兩種類(lèi)型,一種是context instanceof Application,另一種則是普通context。先看看如果是普通的context,這里FragmentActivity、Activity其實(shí)差不多,內(nèi)部創(chuàng)建的fragment支持的類(lèi)型不同。如果是ContextWrapper類(lèi)型則繼續(xù)取到baseContext,遞歸調(diào)用get(context)。那么這里我們看看Activity的場(chǎng)景的源碼this.get((Activity)context):

@NonNull
    public RequestManager get(@NonNull Activity activity) {
        if (Util.isOnBackgroundThread()) {
            return this.get(activity.getApplicationContext());
        } else {
            assertNotDestroyed(activity);
            FragmentManager fm = activity.getFragmentManager();
            return this.fragmentGet(activity, fm, (android.app.Fragment)null, isActivityVisible(activity));
        }
    }

這里的if判斷表示如果當(dāng)前程序是在后臺(tái)運(yùn)行,那么傳入getApplicationContext去get RequestManager ,這里ApplicationContext的情況我們等會(huì)兒?jiǎn)为?dú)再講,繼續(xù)看下面的代碼,我們看到activity.getFragmentManager(),獲取當(dāng)前activity的FragmentManager,然后調(diào)用了fragmentGet方法,那么繼續(xù)看看這個(gè)方法的源碼:

   /** @deprecated */
    @Deprecated
    @NonNull
    private RequestManager fragmentGet(@NonNull Context context, @NonNull FragmentManager fm, @Nullable android.app.Fragment parentHint, boolean isParentVisible) {
        RequestManagerFragment current = this.getRequestManagerFragment(fm, parentHint, isParentVisible);
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
            Glide glide = Glide.get(context);
            requestManager = this.factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
            current.setRequestManager(requestManager);
        }
        return requestManager;
    }

重點(diǎn)來(lái)了,我們看到第一行返回了一個(gè)RequestManagerFragment ,我們跟進(jìn)去看看這個(gè)fragment是怎么創(chuàng)建的:

  @NonNull
    private RequestManagerFragment getRequestManagerFragment(@NonNull FragmentManager fm, @Nullable android.app.Fragment parentHint, boolean isParentVisible) {
        RequestManagerFragment current = (RequestManagerFragment)fm.findFragmentByTag("com.bumptech.glide.manager");
        if (current == null) {
            current = (RequestManagerFragment)this.pendingRequestManagerFragments.get(fm);
            if (current == null) {
                current = new RequestManagerFragment();
                current.setParentFragmentHint(parentHint);
                if (isParentVisible) {
                    current.getGlideLifecycle().onStart();
                }
                this.pendingRequestManagerFragments.put(fm, current);
                fm.beginTransaction().add(current, "com.bumptech.glide.manager").commitAllowingStateLoss();
                this.handler.obtainMessage(1, fm).sendToTarget();
            }
        }
        return current;
    }

這里我們先通過(guò)pendingRequestManagerFragments從緩存中去拿RequestManagerFragment ,這里的pendingRequestManagerFragment就是一個(gè)hashmap,Map<FragmentManager, RequestManagerFragment>,如果緩存中沒(méi)有,那么去new一個(gè)fragment并且將其添加到緩存中,重點(diǎn)來(lái)了, fm.beginTransaction().add(current, "com.bumptech.glide.manager").commitAllowingStateLoss();這里便將一個(gè)沒(méi)有ui的fragment添加到了context對(duì)應(yīng)的activity上?;氐角懊嫖覀兲岬降腶pplicationcontext,看看這種情況,調(diào)用的是getApplicationManager:

 @NonNull
    private RequestManager getApplicationManager(@NonNull Context context) {
        if (this.applicationManager == null) {
            synchronized(this) {
                if (this.applicationManager == null) {
                    Glide glide = Glide.get(context.getApplicationContext());
                    this.applicationManager = this.factory.build(glide, new ApplicationLifecycle(), new EmptyRequestManagerTreeNode(), context.getApplicationContext());
                }
            }
        }
        return this.applicationManager;
    }

這里我們直接看factory的build方法,跟進(jìn)去看一源碼:

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

這里根據(jù)傳入applicationContext去創(chuàng)建一個(gè)RequestManager并返回,到這里整個(gè)with方法就結(jié)束了,我們?cè)倏纯磃ragment對(duì)應(yīng)的生命周期方法中做了什么:

@Override
  public void onDetach() {
    super.onDetach();
    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();
  }

這里可以看出,當(dāng)activity觸發(fā)生命周期的時(shí)候,當(dāng)前無(wú)UI的fragment也會(huì)觸發(fā)相應(yīng)的生命周期方法,那么這里的lifecycle調(diào)用到了哪里呢,跟進(jìn)去發(fā)現(xiàn)調(diào)用的是ActivityFragmentLifecycle實(shí)現(xiàn)的幾個(gè)方法:

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

這里的lifecycleListeners存儲(chǔ)了前面添加的多個(gè)生命周期的監(jiān)聽(tīng),在這里全部觸發(fā),那么這里我們之前添加的
lifecycleListener 包括了RequestManager中的,我們?cè)赗equestManager創(chuàng)建的時(shí)候就已經(jīng)添加了一個(gè)listener到lifecycleListeners中,所以這里的onStart、onStop、onDestroy會(huì)調(diào)用RequestManager里面的對(duì)應(yīng)方法,RequestManager作為一個(gè)管理類(lèi),管理了兩個(gè)重要的對(duì)象,一個(gè)是target,另一個(gè)是request,因此RequestManager通過(guò)監(jiān)聽(tīng)生命周期方法,同時(shí)控制了target和request的加載情況,我們來(lái)看下代碼:

  @Override
  public synchronized void onStart() {
    resumeRequests();
    targetTracker.onStart();
  }

  @Override
  public synchronized void onStop() {
    pauseRequests();
    targetTracker.onStop();
  }

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

可以看到,在對(duì)應(yīng)的生命周期方法中控制了targetTracker和requestTracker,這兩個(gè)對(duì)象則分別控制這target和request的生命周期。到這里我們的width方法源碼流程就結(jié)束了。

RequestManager的load(url)方法

上面我們分析的是Glide.with(this).load(url).into(imageView)中的with方法,那么我們繼續(xù)看load,width返回的是RequestManager,那么自然load方法在RequestManager中,我們看下源碼:

  @Override
public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
    return asDrawable().load(bitmap);
  }

  @Override
  public RequestBuilder<Drawable> load(@Nullable Drawable drawable) {
    return asDrawable().load(drawable);
  }

  @Override
  public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
  }

  @Override
  public RequestBuilder<Drawable> load(@Nullable Uri uri) {
    return asDrawable().load(uri);
  }

  @Override
  public RequestBuilder<Drawable> load(@Nullable File file) {
    return asDrawable().load(file);
  }

  @Override
  public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
    return asDrawable().load(resourceId);
  }

  @Override
  public RequestBuilder<Drawable> load(@Nullable URL url) {
    return asDrawable().load(url);
  }

  @Override
  public RequestBuilder<Drawable> load(@Nullable byte[] model) {
    return asDrawable().load(model);
  }

  @Override
  public RequestBuilder<Drawable> load(@Nullable Object model) {
    return asDrawable().load(model);
  }

glide提供的load方法極多,涵蓋了大多數(shù)的圖片加載資源,例如字節(jié)碼,URL,Drawable,文件,bitmap,字符串的圖片地址等等,這里我們就以常用的字符串的圖片地址為例看下代碼:

  @Override
  public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
  }

  @NonNull
  public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }

  @NonNull
  public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }

  @Override
  @CheckResult
  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;
  }

我們先看asDrawable方法,其實(shí)就是設(shè)置了圖片資源的類(lèi)型,然后創(chuàng)建了一個(gè)RequestBuilder對(duì)象,然后傳入一個(gè)String類(lèi)型并且調(diào)用load方法,這里是將我們的String URL設(shè)置到了model 對(duì)象中,并沒(méi)有開(kāi)始請(qǐng)求,所以我們的重點(diǎn)任務(wù)就放在了into方法中,它包括了獲取內(nèi)存緩存,獲取磁盤(pán)緩存,請(qǐng)求,寫(xiě)入內(nèi)存和磁盤(pán)緩存等許多操作,那么我們下一節(jié)再繼續(xù)分析最重要的一步into方法吧~

總結(jié)

首先通過(guò)width方法中的getRetriever方法,完成Glide的初始化并且獲取到RequestManagerRetriever,RequestManagerRetriever主要用于管理和生成RequestManager,然后通過(guò)RequestManagerRetriever的get方法為activity創(chuàng)建一個(gè)無(wú)UI的fragment,并且綁定到當(dāng)前activity,然后生成一個(gè)RequestManager并且與之關(guān)聯(lián)生命周期,當(dāng)activity的生命周期發(fā)生改變時(shí),通知綁定的fragment,繼而通知到RequestManager的監(jiān)聽(tīng)方法,從而控制對(duì)target和request的加載、暫停和銷(xiāo)毀。

下一節(jié)我們講講into(imageview)中的內(nèi)存緩存:

Glide源碼之into方法后續(xù)讀取內(nèi)存緩存

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容