参考:
Glide4用法官方文档:https://muyangmin.github.io/glide-docs-cn/doc/getting-started.html
Glide3.7.0源码解析:https://blog.youkuaiyun.com/sinyu890807/column/info/15318
《Android面试题:Glide》 https://blog.youkuaiyun.com/songzi1228/article/details/84426165
Q:了解Glide的实现原理吗?
A:了解过,主要有几个方面:
- 图片缓存:内存缓存(LRU缓存+弱引用缓存),磁盘缓存,Bitmap对象池(Bitmap对象复用)
- 请求管理:根据生命周期取消request,重启失败request,请求优先级,缩略图请求管理
- 图片变换,图片解码
零,下载Glide源码
一,开始分析,Glide常用句式Glide.with(fragment).load(myUrl).into(imageView);
先分析第一步Glide.with(context)
with方法是使用Glide加载图片的第一步,Glide类中的静态方法,返回RequestManager对象,根据传入的Context参数类型不同,主要有5个重载的with方法,区别是图片请求生命周期不同。
* @see #with(Context)
* @see #with(android.app.Activity)
* @see #with(android.app.Fragment)
* @see #with(androidx.fragment.app.Fragment)
* @see #with(androidx.fragment.app.FragmentActivity)
Glide可以根据当前页面的生命周期,自动重新开始或暂停或取消结束请求;实现原理就是根据传入的Context类型,在当前页面上生成一个看不见的fragment,来获得当前页面的生命周期的回调,进行请求相关的操作。如果传入的是Application,请求的生命周期将和应用一样长,不会自动取消;如果传入的是Activity或Fragment,当前Activity或Fragment退出时,请求将会自动终止。所以,从内存优化的角度看,应该传入当前页面的Context类型。比如child fragment页面上的Imagview显示图片,应该传入child fragment,而不是parent fragment和fragment所在的Activity。
可以看看源码的注释:
/**
* Begin a load with Glide by passing in a context.
*
* <p>Any requests started using a context will only have the application level options applied
* and will not be started or stopped based on lifecycle events. In general, loads should be
* started at the level the result will be used in. If the resource will be used in a view in a
* child fragment, the load should be started with {@link #with(android.app.Fragment)}} using that
* child fragment. Similarly, if the resource will be used in a view in the parent fragment, the
* load should be started with {@link #with(android.app.Fragment)} using the parent fragment. In
* the same vein, if the resource will be used in a view in an activity, the load should be
* started with {@link #with(android.app.Activity)}}.
*
* <p>This method is appropriate for resources that will be used outside of the normal fragment or
* activity lifecycle (For example in services, or for notification thumbnails).
*
* @param context Any context, will not be retained.
* @return A RequestManager for the top level application that can be used to start a load.
* @see #with(android.app.Activity)
* @see #with(android.app.Fragment)
* @see #with(androidx.fragment.app.Fragment)
* @see #with(androidx.fragment.app.FragmentActivity)
*/
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
所有with方法里面都是一句话,最终都是1.先调用getRetriever(context)方法获得RequestManagerRetriever对象,2.再调用RequestManagerRetriever对象的get(context)方法获得RequestManager对象。
RequestManagerRetriever这个类干嘛用的呢?源码里面的注释:A collection of static methods for creating new RequestManager or retrieving existing ones from activities and fragment.一些静态方法的集合,这些方法是用来创建新的requestManager对象或从activities和fragment中取回已存在的requestManager对象。
1.先看getRetriever(context)方法,
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
// Context could be null for other reasons (ie the user passes in null), but in practice it will
// only occur due to errors with the Fragment lifecycle.
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 Glide.get(context).getRequestManagerRetriever();
}
getRetriever(context)方法里面通过Glide.get(context)方法获取Glide单例对象,再调用getRequestManagerRetriever()简单的将requestManagerRetriever对象返回。在创建Glide单例对象的过程中,会创建并持有一个requestManagerRetriever对象。Glide单例对象在get方法里创建,这里先不跟进去看。(TODO:Glide的创建)
2.再看RequestManagerRetriever对象的get(context)方法,get方法和Glide里面的with方法一样有多个context子类参数的重载。
* @see #get(Context)
* @see #get(android.app.Activity)
* @see #get(android.app.Fragment)
* @see #get(androidx.fragment.app.Fragment)
* @see #get(androidx.fragment.app.FragmentActivity)
每个方法都看有点眼花,我们先看看其中的get(android.app.Activity)方法的实现
,(TODO:重载的get方法)
/**
* A collection of static methods for creating new {@link com.bumptech.glide.RequestManager}s or
* retrieving existing ones from activities and fragment.
*/
public class RequestManagerRetriever implements Handler.Callback {
......
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));
}
}
......
}
get(android.app.Activity)里面,先判断是否是后台线程,(如果是后台线程,请求无需根据activity页面的销毁而结束了),就直接调用参数ApplicationContext的get(Context)方法,创建一个和Application生命周期一样长的请求。如果是主线程,调用了fragmentGet方法并返回。
那么看看fragmenGet()方法:
private RequestManager fragmentGet(
@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
fragmenGet()方法里面,调用getRequestManagerFragment返回了一个fragment对象RequestManagerFragment,并创建一个RequestManager与fragment对象绑定,最后返回了RequestManager。
那么看看getRequestManagerFragment()方法:
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
getRequestManagerFragment()方法里面,new RequestManagerFragment,并通过传入的FragmentManager添加到了页面上。从这里可以看出,RequestManagerFragment是根据页面的生命周期来管理Glide request请求的关键人物了。
那么看看RequestManagerFragment类里有什么,(可以源码的类的注释,一般都很清楚地描述了类的功能)
/**
* A view-less {@link android.app.Fragment} used to safely store an {@link
* com.bumptech.glide.RequestManager} that can be used to start, stop and manage Glide requests
* started for targets the fragment or activity this fragment is a child of.
*
* @see com.bumptech.glide.manager.SupportRequestManagerFragment
* @see com.bumptech.glide.manager.RequestManagerRetriever
* @see com.bumptech.glide.RequestManager
*/
@SuppressWarnings("DeprecatedIsStillUsed")
@Deprecated
public class RequestManagerFragment extends Fragment {
......
private final ActivityFragmentLifecycle lifecycle;
private RequestManager requestManager;
public RequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
RequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
public void setRequestManager(@Nullable RequestManager requestManager) {
this.requestManager = requestManager;
}
public RequestManager getRequestManager() {
return requestManager;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
registerFragmentWithRoot(activity);
} catch (IllegalStateException e) {
// OnAttach can be called after the activity is destroyed, see #497.
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Unable to register fragment with root", e);
}
}
}
@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();
}
private void registerFragmentWithRoot(@NonNull Activity activity) {
unregisterFragmentWithRoot();
rootRequestManagerFragment =
Glide.get(activity).getRequestManagerRetriever().getRequestManagerFragment(activity);
if (!equals(rootRequestManagerFragment)) {
rootRequestManagerFragment.addChildRequestManagerFragment(this);
}
}
private void unregisterFragmentWithRoot() {
if (rootRequestManagerFragment != null) {
rootRequestManagerFragment.removeChildRequestManagerFragment(this);
rootRequestManagerFragment = null;
}
}
......
}
RequestManagerFragment类继承Fragemt类,在onAttach,onDetach方法中分别调用了registerFragmentWithRoot,unregisterFragmentWithRoot实现子fragment的添加和移除。RequestManagerFragment的构造方法中new ActivityFragmentLifecycle对象,并且在onStart,onStop,onDestroy中分别调用了ActivityFragmentLifecycle对象的onStart,onStop,onDestroy方法,看来就是通过ActivityFragmentLifecycle保存和通知页面的生命周期状态的变化。
那么看看ActivityFragmentLifecycle类,
/**
* A {@link com.bumptech.glide.manager.Lifecycle} implementation for tracking and notifying
* listeners of {@link android.app.Fragment} and {@link android.app.Activity} lifecycle events.
*/
class ActivityFragmentLifecycle implements Lifecycle {
private final Set<LifecycleListener> lifecycleListeners =
Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
private boolean isStarted;
private boolean isDestroyed;
/**
* Adds the given listener to the list of listeners to be notified on each lifecycle event.
*
* <p>The latest lifecycle event will be called on the given listener synchronously in this
* method. If the activity or fragment is stopped, {@link LifecycleListener#onStop()}} will be
* called, and same for onStart and onDestroy.
*
* <p>Note - {@link com.bumptech.glide.manager.LifecycleListener}s that are added more than once
* will have their lifecycle methods called more than once. It is the caller's responsibility to
* avoid adding listeners multiple times.
*/