基本調(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