從源碼的角度帶你分析Glide整體加載流程以及設(shè)計(jì)模式

基本調(diào)用流程

這一篇文章我們從源碼的角度分析Glide實(shí)現(xiàn),首先我們從一句最簡單的使用方式來探索他的設(shè)計(jì)與實(shí)現(xiàn),可以看到下面這句話是最基礎(chǔ)的使用

Glide.with(this)
        .load(R.raw.large_giphy_logo)
        .into(giphyLogoView);

接下來我們一步一步的跟蹤他的調(diào)用過程,首先我們看到他調(diào)用了Glide的with方法并傳入了自己的引用,我們可以看到這方法的實(shí)現(xiàn)如下:

public static RequestManager with(Activity activity) {
  RequestManagerRetriever retriever = RequestManagerRetriever.get();
  return retriever.get(activity);
}

他調(diào)用了RequestManagerRetriever的方法獲取了一個(gè)RequestManagerRetriever然后在調(diào)用get方法獲取了一個(gè)RequestManager,到這里我們大概基本明白了with方法做的是將當(dāng)前引用(Activity,F(xiàn)ragment)傳遞進(jìn)去并獲取一個(gè)和當(dāng)前引用綁定的RequestManager,到這里大家應(yīng)該能明白了為什么說Glide綁定了界面的生命周期了吧

接著調(diào)用了RequestManager的load方法,可以看到這一步創(chuàng)建了RequestBuilder

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

最后調(diào)用到了loadGeneric方法

public RequestBuilder<TranscodeType> load(@Nullable Object model) {
  return loadGeneric(model);
}

不過從這個(gè)方法我們可以看到他只是將傳遞進(jìn)來的資源保存了,現(xiàn)在還沒有發(fā)送真正的網(wǎng)絡(luò)請(qǐng)求

private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
  this.model = model;
  isModelSet = true;
  return this;
}

然后調(diào)用了RequestBuilder的into方法

public Target<TranscodeType> into(ImageView view) {
    Util.assertMainThread();
    Preconditions.checkNotNull(view);

    if (!requestOptions.isTransformationSet()
            && requestOptions.isTransformationAllowed()
            && view.getScaleType() != null) {
        if (requestOptions.isLocked()) {
            requestOptions = requestOptions.clone();
        }
        switch (view.getScaleType()) {
            case CENTER_CROP:
                requestOptions.optionalCenterCrop(context);
                break;
            case CENTER_INSIDE:
                requestOptions.optionalCenterInside(context);
                break;
            case FIT_CENTER:
            case FIT_START:
            case FIT_END:
                requestOptions.optionalFitCenter(context);
                break;
            //$CASES-OMITTED$
            default:
                // Do nothing.
        }
    }

    return into(context.buildImageViewTarget(view, transcodeClass));
}

在這個(gè)方法里面,主要判斷了是否設(shè)置了Transformation如果設(shè)置了,然后根據(jù)相應(yīng)的規(guī)則變換bitmap,最后調(diào)用了這個(gè)into方法

public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
    Util.assertMainThread();
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
        throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    Request previous = target.getRequest();

    if (previous != null) {
        requestManager.clear(target);
    }

    requestOptions.lock();
    Request request = buildRequest(target);
    target.setRequest(request);
    requestManager.track(target, request);

    return target;
}

在這方法中創(chuàng)建了Request,然后調(diào)用requestManager的track方法去執(zhí)行這個(gè)request

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

我們再來查看下buildRequest方法

  private Request buildRequest(Target<TranscodeType> target) {
    return buildRequestRecursive(target, null, transitionOptions, requestOptions.getPriority(),
            requestOptions.getOverrideWidth(), requestOptions.getOverrideHeight());
}

private Request buildRequestRecursive(Target<TranscodeType> target,
                                      @Nullable ThumbnailRequestCoordinator parentCoordinator,
                                      TransitionOptions<?, ? super TranscodeType> transitionOptions,
                                      Priority priority, int overrideWidth, int overrideHeight) {
    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;
        if (DEFAULT_ANIMATION_OPTIONS.equals(thumbTransitionOptions)) {
            thumbTransitionOptions = transitionOptions;
        }

        Priority thumbPriority = thumbnailBuilder.requestOptions.isPrioritySet()
                ? thumbnailBuilder.requestOptions.getPriority() : getThumbnailPriority(priority);

        int thumbOverrideWidth = thumbnailBuilder.requestOptions.getOverrideWidth();
        int thumbOverrideHeight = thumbnailBuilder.requestOptions.getOverrideHeight();
        if (Util.isValidDimensions(overrideWidth, overrideHeight)
                && !thumbnailBuilder.requestOptions.isValidOverride()) {
            thumbOverrideWidth = requestOptions.getOverrideWidth();
            thumbOverrideHeight = requestOptions.getOverrideHeight();
        }

        ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
        Request fullRequest = obtainRequest(target, requestOptions, coordinator,
                transitionOptions, priority, overrideWidth, overrideHeight);
        isThumbnailBuilt = true;
        // Recursively generate thumbnail requests.
        Request thumbRequest = thumbnailBuilder.buildRequestRecursive(target, coordinator,
                thumbTransitionOptions, thumbPriority, thumbOverrideWidth, thumbOverrideHeight);
        isThumbnailBuilt = false;
        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(target, requestOptions, coordinator, transitionOptions,
                priority, overrideWidth, overrideHeight);
        BaseRequestOptions<?> thumbnailOptions = requestOptions.clone()
                .sizeMultiplier(thumbSizeMultiplier);

        Request thumbnailRequest = obtainRequest(target, thumbnailOptions, coordinator,
                transitionOptions, getThumbnailPriority(priority), overrideWidth, overrideHeight);

        coordinator.setRequests(fullRequest, thumbnailRequest);
        return coordinator;
    } else {
        // Base case: no thumbnail.
        return obtainRequest(target, requestOptions, parentCoordinator, transitionOptions, priority,
                overrideWidth, overrideHeight);
    }
}

可以看到最后調(diào)用了buildRequestRecursive來創(chuàng)建一個(gè)Request,在這方法里面通過判斷是否設(shè)置了thumbnail來創(chuàng)建不同類型的Request,如果沒有設(shè)置就會(huì)創(chuàng)建最基本的請(qǐng)求,也就是SingleRequest

private Request obtainRequest(Target<TranscodeType> target,
                              BaseRequestOptions<?> requestOptions, RequestCoordinator requestCoordinator,
                              TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority,
                              int overrideWidth, int overrideHeight) {
    requestOptions.lock();

    return SingleRequest.obtain(
            context,
            model,
            transcodeClass,
            requestOptions,
            overrideWidth,
            overrideHeight,
            priority,
            target,
            requestListener,
            requestCoordinator,
            context.getEngine(),
            transitionOptions.getTransitionFactory());
}

到這里大家可以看到Glide的源碼可以說是非常復(fù)雜的,總感覺有時(shí)候用到項(xiàng)目里是不是有點(diǎn)太重了,就加載個(gè)圖片,你看看搞了這么多代碼~~

一些設(shè)計(jì)技巧

綁定界面的生命周期

在Glide中可以看到所有的請(qǐng)求都是和當(dāng)前界面綁定的,比如:activity執(zhí)行onStop時(shí),其相應(yīng)的請(qǐng)求應(yīng)該暫停,那他是怎么綁定的呢,簡單來講就是在當(dāng)前activity中綁定一個(gè)fragment,這樣我們就能通過這個(gè)fragment獲取到相應(yīng)的生命周期,然后回調(diào)到你要處理的地方,然后在作出相應(yīng)的處理,如果代碼:

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void bindLifeCycle(LifeCycleActivity activity) {
    FragmentManager fm = activity.getFragmentManager();
    //將一個(gè)fragment綁定到當(dāng)前界面,這樣就能獲取到了當(dāng)前界面的生命周期了
    LifeCycleFragment current = new LifeCycleFragment();
    fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
}

這樣我們就能在LifeCycleFragment中獲取到相應(yīng)的生命周期了

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class LifeCycleFragment extends Fragment {
    private static final String TAG = "LifeCycleFragment";

    @Override
    public void onStart() {
        super.onStart();
        //TODO 這里回調(diào)你的生命周期狀態(tài)
        Log.d(TAG,"onStart");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d(TAG,"onStop");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG,"onDestroy");
    }
}

參考:https://github.com/android-cn/android-open-project-analysis/tree/master/tool-lib/image-cache/glide

最后編輯于
?著作權(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)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,928評(píng)論 25 709
  • 聲明 本文章是基于 glide 3.6.1的 個(gè)各類的功能介紹 1.Glide:向外暴露單例靜態(tài)接口,構(gòu)建Requ...
    河里的枇杷樹閱讀 1,285評(píng)論 0 3
  • 本文是Glide源碼解析系列的第一篇,通過這篇文檔,將可以了解到: 1.Glide如何綁定Activity、Fra...
    他的大姨父閱讀 8,754評(píng)論 6 42
  • 六月十二那天,陽光很好,風(fēng)輕輕吹著。西瓜結(jié)束了作為初中生的最重要的一次考試。西瓜以為自己會(huì)像文里寫的那樣哭泣,那樣...
    桃夭公子閱讀 360評(píng)論 2 4
  • 2017年10月22日星期日 距離18考研61天 早晨6點(diǎn)40起床,7點(diǎn)40到教室。 復(fù)習(xí)政治選擇題。 數(shù)學(xué)做的線...
    sy_yunyi閱讀 356評(píng)論 0 0

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