逐步分析
Glide.with(……)
Glide.with() 有下面几种实现方式。
1 2 3 4 5
| 1. Glide.with(Context context) 2. Glide.with(Activity activity) 3. Glide.with(FragmentActivity activity) 4. Glide.with(android.app.Fragment fragment) 5. Glide.with(View view)
|
所以的方法实现也是很类似,都是调用同一个方法
1 2 3
| public static RequestManager with(Fragment fragment) { return getRetriever(fragment.getActivity()).get(fragment); }
|
再看一下 getRetriever() 方法
1 2 3 4 5 6
| private static RequestManagerRetriever getRetriever(@Nullable Context context) { …… 省略一些判空检查 —— return Glide.get(context).getRequestManagerRetriever(); }
|
其中 Glide.get(context) 主要用来初始化 Glide 的全局单利对象,以及一些配置。
getRequestManagerRetriever() 则是返回 Glide 对象的 requestManagerRetriever 对象。
然后看一下 requestManagerRetriever.get() 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public RequestManager get(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); }
|
get() 方法会根据传入的 context 对象和当前线程,创建不同的 RequestManager 实例
1 2 3 4 5
| 1. 非 UI 线程,返回 applicationManager 对象,能感知 Application 生命周期。 2. UI 线程,如果 context 是 Activity 、FragmentActivity 则会创建一个能感知对应 Activity 的 RequestManager。 3. UI 线程,如果 Context 是 Fragment、android.support.v4.app.Fragment 则会创建一个能感知对应 Fragment 生命周期 的 RequestManager。
|
这里反复提到了一个 感知生命 xx 周期
,也是 Glide 的一个特性。
1 2 3
| Glide 在加载资源的时候,如果是在 Activity、Fragment 这一类有生命周期的组件上进行。 当 Activity、Fragment 等组件进入不可见,或者已经销毁的时候,Glide 会停止加载资源。 Application 的生命周期贯穿整个应用,所以 applicationManager 只有在应用程序关闭的时候终止加载。
|
所以尽量不要在非 UI 线程使用 Glide 加载图片,尽量使用 Activity、Fragment 等带有生命周期的组件配合 Glide 使用。
Glide 如何获得 Activity、Fragment 生命周期回调
在 各种 requestManagerRetriever.get() 方法中如果传入的是带有生命周期的组件,并且在 UI 线程,会执行以下几个方法端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| assertNotDestroyed(activity); FragmentManager fm = activity.getSupportFragmentManager(); return supportFragmentGet(activity, fm, null );
FragmentManager fm = fragment.getChildFragmentManager(); return supportFragmentGet(fragment.getActivity(), fm, fragment);
assertNotDestroyed(activity); android.app.FragmentManager fm = activity.getFragmentManager(); return fragmentGet(activity, fm, null );
android.app.FragmentManager fm = fragment.getChildFragmentManager(); return fragmentGet(fragment.getActivity(), fm, fragment);
|
- 如果是 Activity ,先获取 FragmentManager ,如果是 Fragment 则先获取 ChildFragmentManager。
- 如果是 support 包下面的 Activity 、Fragment 调用 supportFragmentGet,否则调用 fragmentGet。
fragmentGet() 和 supportFragmentGet() 方法大致类似,选取一个分析一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| private RequestManager fragmentGet(Context context, android.app.FragmentManager fm, android.app.Fragment parentHint) { RequestManagerFragment current = getRequestManagerFragment(fm, parentHint); RequestManager requestManager = current.getRequestManager(); if (requestManager == null) { Glide glide = Glide.get(context); requestManager = factory.build( glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context); current.setRequestManager(requestManager); } return requestManager; }
|
上面这段代码做了两个功能
1 2
| 1. 创建一个 RequestManagerFragment。 2. 创建一个 RequestManager。
|
先看一下 getRequestManagerFragment
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) RequestManagerFragment getRequestManagerFragment( final android.app.FragmentManager fm, android.app.Fragment parentHint) { RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); if (current == null) { current = pendingRequestManagerFragments.get(fm); if (current == null) { current = new RequestManagerFragment(); current.setParentFragmentHint(parentHint); pendingRequestManagerFragments.put(fm, current); fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget(); } } return current; }
|
这是是 Glide 设计中比较一个巧妙的地方
1 2
| 创建一个透明的 RequestManagerFragment 加入到FragmentManager 之中 通过添加的这个 Fragment 感知 Activity 、Fragment 的生命周期。
|
在 RequestManagerFragment 中可以看到以下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @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(); }
|
可以通过 RequestManagerFragment 把 Activity 的生命周期通过 lifecycle 传递给在 lifecycle 注册的 LifecycleListener。
RequestManager.load(url)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public RequestBuilder<Drawable> load(@Nullable Object model) { return asDrawable().load(model); }
public RequestBuilder<Drawable> asDrawable() { return as(Drawable.class); }
public <ResourceType> RequestBuilder<ResourceType> as(Class<ResourceType> resourceClass) { return new RequestBuilder<>(glide, this, resourceClass, context); }
public RequestBuilder<TranscodeType> load(@Nullable Object model) { return loadGeneric(model); }
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) { this.model = model; isModelSet = true; return this; }
|
以上就是 RequestBuilder.load(url) 的相关代码,发现并没有什么特殊之处。 只是创建了一个 RequestBuilder 。
RequestBuilder.into(view)
into() 方法调用起来十分方便,只要传递一个 ImageView ,Glide 就会自动下载图片,并且显示到 ImageView 上。这看似十分简单的一步,也是 Glide 最负责的调用。
1 2 3 4 5 6 7 8 9 10
| public Target<TranscodeType> into(ImageView view) { RequestOptions requestOptions = this.requestOptions; …… return into( glideContext.buildImageViewTarget(view, transcodeClass), null, requestOptions); }
|
跟踪一下 glideContext.buildImageViewTarget(view, transcodeClass) 会发现这里返回的是一个DrawableImageViewTarget
into(ImageView view) 把 requestOptions 和 DrawableImageViewTarget 传入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| private <Y extends Target<TranscodeType>> Y into( @NonNull Y target, @Nullable RequestListener<TranscodeType> targetListener, RequestOptions options) { …… Request request = buildRequest(target, targetListener, options);
Request previous = target.getRequest(); …… requestManager.clear(target); target.setRequest(request); requestManager.track(target, request);
return target; }
|
下一步跟踪到 requestManager.track(target, request)
1 2 3 4 5 6 7 8 9 10 11 12 13
| void track(Target<?> target, Request request) { targetTracker.track(target); requestTracker.runRequest(request); }
public void runRequest(Request request) { requests.add(request); if (!isPaused) { request.begin(); } else { pendingRequests.add(request); } }
|
isPaused 变量
1 2 3 4 5
| 1. 如果此时 GlideRequests 的 Lifecycle 为 ApplicationLifecycle,只要应用存活 isPaused 为 false ,直接执行 request.begin() 2. 如果 GlideRequests 的 Lifecycle 是观测 Fragment 或者 Activity isPaused 为true ,不会立即执行 request.begin() 当 Fragment 或者 Activity 显示到前台时通过遍历 requests 数组执行 request.begin()
|
所以执行网络请求下载图片的操作在 request.begin() 之中。
回到 into(ImageView view) 方法的
1
| Request request = buildRequest(target, targetListener, options)
|
经过层层包裹我们可以找到一下路线,发现最后返回的是 SingleRequest
1 2 3
| buildRequest >> buildRequestRecursive >> buildThumbnailRequestRecursive
>> obtainRequest >> SingleRequest
|
创建 SingleRequest 的过程比较复杂,牵扯到缩略图、错误处理之类的逻辑,大致都是上面那条路径。
然后就看一下 SingleRequest.begin()
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Override public void begin() { …… 省略一些其他分支 …… status = Status.WAITING_FOR_SIZE; if (Util.isValidDimensions(overrideWidth, overrideHeight)) { onSizeReady(overrideWidth, overrideHeight); } else { target.getSize(this); } …… …… }
|
begin() 方法很长,我们剔除了一些异常处理,直接看最核心的方法。
如果我给 Glide 设置了 override() 则直接调用 onSizeReady(overrideWidth, overrideHeight)
否则会调用 target.getSize(this) 让 ImageView 计算自己的尺寸。
1
| glideContext.buildImageViewTarget(view, transcodeClass) 创建一个 DrawableImageViewTarget
|
Glide流程
Glide网络下载流程
总结
- 缓存
- 活动资源 (Active Resources)
- 内存缓存 (Memory Cache)
- 资源类型(Resource Disk Cache)
- 原始数据 (Data Disk Cache)
- 网络缓存