熟悉Glide的同学都知道,Glide加载图片是和Activity/Fragment生命周期相关联的,具体来说在onStart()发起请求或重新请求,onStop()暂停正在进行的请求,onDestory()取消清除请求。这样的好处是节约资源,避免内存泄漏。本文源码基于Glide 4.9.0
1.关联生命周期的核心类
- Glide:供外部调用的核心类,外观模式;
- RequestManagerRetriever:关联RequestManager和SupportRequestManagerFragment/RequestManagerFragment的中间类
- RequetManager:用来加载,管理图片请求的,会结合Activity/Fragment生命周期对请求进行管理;
- SupportRequstManagerFragment/RequestManagerFragment:Glide内部创建无UI的fragment,会与当前Activity绑定,与RequestManager绑定,传递页面的生命周期。
- ActivityFragmentLifecycle:保存fragment和Requestmanager映射关系的类,管理LifecycleListener;
- LifecycleListener;定义生命周期管理方法的接口,onStart(),onStop(),onDestory().
2.关联生命周期的核心流程
这部分主要讲RequestManager加载/管理 请求的时候是如何感知当前Activity/Fragment生命周期的.
Glide加载图片最基本的方式
Glide.with(context).load("xxx").into(imageView)
with有多个方法重载
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);
}
@NonNull
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
getRetriever方法:
@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();
}
Glide类
//Glide.get(context)
/**
* Get the singleton.
*
* @return the singleton
*/
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
private static void checkAndInitializeGlide(@NonNull Context context) {
// In the thread running initGlide(), one or more classes may call Glide.get(context).
// Without this check, those calls could trigger infinite recursion.
if (isInitializing) {
throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
+ " use the provided Glide instance instead");
}
isInitializing = true;
initializeGlide(context);
isInitializing = false;
}
/**
* Internal method.
*/
//构造方法传入
@NonNull
public RequestManagerRetriever getRequestManagerRetriever() {
return requestManagerRetriever;
}
RequestManagerRetriever类
/**
* 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 {
//..........
private final RequestManagerFactory factory;
/**
* Pending adds for SupportRequestManagerFragments.
*/
@VisibleForTesting
final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
new HashMap<>();
@NonNull
private RequestManager getApplicationManager(@NonNull Context context) {
// Either an application context or we're on a background thread.
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
// Normally pause/resume is taken care of by the fragment we add to the fragment or
// activity. However, in this case since the manager attached to the application will not
// receive lifecycle events, we must force the manager to start resumed using
// ApplicationLifecycle.
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context.getApplicationContext());
applicationManager =
factory.build(
glide,
new ApplicationLifecycle(),
new EmptyRequestManagerTreeNode(),
context.getApplicationContext());
}
}
}
return applicationManager;
}
@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 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);
}
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
//获取当前Activity的FragmentManager
//用于后续将创建的Fragment绑定到Activity
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(
activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
@NonNull
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible) {
//创建无UI的Fragment,并绑定到当前Activity
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(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,获取fragment的lifecycle,并传入requestManger
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
//fragment与RequestManager关联
current.setRequestManager(requestManager);
}
return requestManager;
}
@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
// 1.通过FragmentManager的findFragmentByTag获取Fragment对象
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
// 2.从缓存集合中获取fragment,map以fragment为key 以fragment对象为value进行存储
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
// 3.创建一个fragment实例
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
// 将创建的Fragment放入HashMap缓存
pendingSupportRequestManagerFragments.put(fm, current);
// 提交事物,将fragment绑定到Activity
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
// 发消息,从map缓存中删除fragment
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
@Override
public boolean handleMessage(Message message) {
boolean handled = true;
Object removed = null;
Object key = null;
switch (message.what) {
case ID_REMOVE_FRAGMENT_MANAGER:
android.app.FragmentManager fm = (android.app.FragmentManager) message.obj;
key = fm;
removed = pendingRequestManagerFragments.remove(fm);
break;
case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
FragmentManager supportFm = (FragmentManager) message.obj;
key = supportFm;
// 从map缓存中删除fragment
removed = pendingSupportRequestManagerFragments.remove(supportFm);
break;
default:
handled = false;
break;
}
if (handled && removed == null && Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Failed to remove expected request manager fragment, manager: " + key);
}
return handled;
}
/**
* Used internally to create {@link RequestManager}s.
*/
public interface RequestManagerFactory {
@NonNull
RequestManager build(
@NonNull Glide glide,
@NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode,
@NonNull Context context);
}
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);
}
};
}
这里有个问题很奇怪,刚把创建的fragment对象放入map缓存起来,但是马上又通过handler把它删除,这是什么情况?
原因是这样的,当调用FragmentManager的add()方法时,是通过开启事务的方式来进行绑定的,这个过程是异步的,具体来说,就是调用add方法时,并不是马上就和activity绑定好了,而是通过Hander来处理的
举个例子:
@Override
protected void onStart() {
super.onStart();
Glide.with(this).load("xx").into(image1);
Glide.with(this).load("xx").into(image2);
}
1、在第一次调用第一行代码的时候,会生成一个Fragment对象,通过FragmentManager出发Fragment于Activity绑定,这个绑定过程是通过Handler发消息来完成的,假设这个消息为m1;
2、紧接着使用Handler来发送消息从HashMap中删除刚才保存的Fragment,假设这个消息为m2;
3、由于是异步的,在消息未处理之前已经开始执行第二行Glide代码了,具体说可能是m1,m2还没有处理,就已经开始调用getSupportRequestManagerFragment方法了,这个方法内部是获取Fragment对象的,具体分析上面说过了;如果不用map来缓存fragment,那么代码流程应该是这样的
此时通过findFragmentByTag还没有找到Fragment,就会重新生成一个Fragment,这是Glide所不允许的,每一个Activity或者Fragment在使用Glide时,只能有一个所依附的虚拟的Fragment。所以将之前所生成的Fragment存储到HashMap中,这样就不会重复生成。等到SupportRequestManagerFragment与Activity绑定完成后,也就是消息m1处理完成后,再将Fragment从Map中销毁。
SupportRequestManagerFragment类
/**
* A view-less {@link android.support.v4.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 within the fragment or activity this fragment is a child of.
*
* @see com.bumptech.glide.manager.RequestManagerFragment
* @see com.bumptech.glide.manager.RequestManagerRetriever
* @see com.bumptech.glide.RequestManager
*/
public class SupportRequestManagerFragment extends Fragment {
.....
private final ActivityFragmentLifecycle lifecycle;
//创建Fragment的时候会创建ActivityFragmentLifecycle对象
public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
@VisibleForTesting
@SuppressLint("ValidFragment")
public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
/**
* Sets the current {@link com.bumptech.glide.RequestManager}.
*
* @param requestManager The manager to put.
*/
public void setRequestManager(@Nullable RequestManager requestManager) {
this.requestManager = requestManager;
}
@NonNull
ActivityFragmentLifecycle getGlideLifecycle() {
return lifecycle;
}
/**
* Returns the current {@link com.bumptech.glide.RequestManager} or null if none is put.
*/
@Nullable
public RequestManager getRequestManager() {
return requestManager;
}
//在Fragment生命周期方法中调用Lifecycle的相关方法来通知RequestManager
@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();
}
}
ActivityFragmentLifecycle.java
/**
* 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>
*
* <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. </p>
*/
@Override
public void addListener(@NonNull LifecycleListener listener) {
lifecycleListeners.add(listener);
if (isDestroyed) {
listener.onDestroy();
} else if (isStarted) {
listener.onStart();
} else {
listener.onStop();
}
}
@Override
public void removeListener(@NonNull LifecycleListener listener) {
lifecycleListeners.remove(listener);
}
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();
}
}
}
LifecycleListener是一个接口,Lifecycle最终是调用了lifecycleListener来通知相关的实现类,也就是RequestManager。
RequestManager类
/**
* A class for managing and starting requests for Glide. Can use activity, fragment and connectivity
* lifecycle events to intelligently stop, start, and restart requests. Retrieve either by
* instantiating a new object, or to take advantage built in Activity and Fragment lifecycle
* handling, use the static Glide.load methods with your Fragment or Activity.
*
* @see Glide#with(android.app.Activity)
* @see Glide#with(android.support.v4.app.FragmentActivity)
* @see Glide#with(android.app.Fragment)
* @see Glide#with(android.support.v4.app.Fragment)
* @see Glide#with(Context)
*/
public class RequestManager implements LifecycleListener,
ModelTypes<RequestBuilder<Drawable>> {
private static final RequestOptions DECODE_TYPE_BITMAP = decodeTypeOf(Bitmap.class).lock();
private static final RequestOptions DECODE_TYPE_GIF = decodeTypeOf(GifDrawable.class).lock();
private static final RequestOptions DOWNLOAD_ONLY_OPTIONS =
diskCacheStrategyOf(DiskCacheStrategy.DATA).priority(Priority.LOW)
.skipMemoryCache(true);
protected final Glide glide;
protected final Context context;
@SuppressWarnings("WeakerAccess")
@Synthetic final Lifecycle lifecycle;
@GuardedBy("this")
private final RequestTracker requestTracker;
@GuardedBy("this")
private final RequestManagerTreeNode treeNode;
@GuardedBy("this")
private final TargetTracker targetTracker = new TargetTracker();
private final Runnable addSelfToLifecycle = new Runnable() {
@Override
public void run() {
lifecycle.addListener(RequestManager.this);
}
};
private final Handler mainHandler = new Handler(Looper.getMainLooper());
private final ConnectivityMonitor connectivityMonitor;
// Adding default listeners should be much less common than starting new requests. We want
// some way of making sure that requests don't mutate our listeners without creating a new copy of
// the list each time a request is started.
private final CopyOnWriteArrayList<RequestListener<Object>> defaultRequestListeners;
@GuardedBy("this")
private RequestOptions requestOptions;
public RequestManager(
@NonNull Glide glide, @NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
this(
glide,
lifecycle,
treeNode,
new RequestTracker(),
glide.getConnectivityMonitorFactory(),
context);
}
// Our usage is safe here.
@SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
RequestManager(
Glide glide,
Lifecycle lifecycle,
RequestManagerTreeNode treeNode,
RequestTracker requestTracker,
ConnectivityMonitorFactory factory,
Context context) {
this.glide = glide;
this.lifecycle = lifecycle;
this.treeNode = treeNode;
this.requestTracker = requestTracker;
this.context = context;
connectivityMonitor =
factory.build(
context.getApplicationContext(),
new RequestManagerConnectivityListener(requestTracker));
// If we're the application level request manager, we may be created on a background thread.
// In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
// issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
// This should be entirely safe.
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
defaultRequestListeners =
new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
glide.registerRequestManager(this);
}
/**
* Lifecycle callback that registers for connectivity events (if the
* android.permission.ACCESS_NETWORK_STATE permission is present) and restarts failed or paused
* requests.
*/
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
/**
* Lifecycle callback that unregisters for connectivity events (if the
* android.permission.ACCESS_NETWORK_STATE permission is present) and pauses in progress loads.
*/
@Override
public synchronized void onStop() {
pauseRequests();
targetTracker.onStop();
}
/**
* Lifecycle callback that cancels all in progress requests and clears and recycles resources for
* all completed requests.
*/
@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);
}
}
小结
1.创建一个无UI的Fragment,具体来说就是SupportRequestManagerFragment/RequestManagerFragment,并绑定到当前Activity,这样Fragment就可以感知Activity的生命周期;
2.在创建Fragment时,初始化Lifecycle,LifecycleListener,并且在生命周期的onStart(),onStop(),onDestory()中调用相关方法;
3.在创建RequestManger的时候传入Lifecycle对象,并且LifecycleListener实现了LifecycleListener接口;
4.这样当生命周期变化的时候,就能通过接口回调去通知RequestManager处理请求.