这篇摸清一个问题,Glide是怎么实现生命周期管理的?
前面已经分析过Glide通过创建一个隐藏的fragment添加到Activity中通过系统生命周期方法的回调,来管理图片加载生命周期.
我们来看下这个隐藏fragment的创建过程:
在RequestManagerRetriever.java中,RequestManagerRetriever是一个创建RequestManager和RequestManagerFragment(隐藏fragment),并将两者联系起来的类.
@NonNull
private RequestManager fragmentGet(@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint) {
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
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;
}
@NonNull
private RequestManager supportFragmentGet(@NonNull Context context, @NonNull FragmentManager fm,
@Nullable Fragment parentHint) {
//获取隐藏fragment
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
//创建requestmanager
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
//将requestManager和隐藏fragment联系起来
current.setRequestManager(requestManager);
}
return requestManager;
}
上面两个方法是创建RequestManager,分别在context对应Activity和FragmentActivity时调用,分析第二个方法.
SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
//从Map缓存中取
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
//存到Map缓存
pendingSupportRequestManagerFragments.put(fm, current);
//添加到当前Activity
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
//发送一个消息移除在Map缓存中的当前fm对应的RequestManagerFragment
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
来看下隐藏fragment -----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 static final String TAG = "SupportRMFragment";
private final ActivityFragmentLifecycle lifecycle;
private final RequestManagerTreeNode requestManagerTreeNode =
new SupportFragmentRequestManagerTreeNode();
private final Set childRequestManagerFragments = new HashSet<>();
@Nullable private SupportRequestManagerFragment rootRequestManagerFragment;
@Nullable private RequestManager requestManager;
@Nullable private Fragment parentFragmentHint;
public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
// For testing only.
@SuppressLint("ValidFragment")
public SupportRequestManagerFragment(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;
}
ActivityFragmentLifecycle getGlideLifecycle() {
return lifecycle;
}
/**
* Returns the current {@link com.bumptech.glide.RequestManager} or null if none is put.
*/
@Nullable
public RequestManager getRequestManager() {
return requestManager;
}
/**
* Returns the {@link RequestManagerTreeNode} that provides tree traversal methods relative
* to the
* associated {@link RequestManager}.
*/
public RequestManagerTreeNode getRequestManagerTreeNode() {
return requestManagerTreeNode;
}
private void addChildRequestManagerFragment(SupportRequestManagerFragment child) {
childRequestManagerFragments.add(child);
}
private void removeChildRequestManagerFragment(SupportRequestManagerFragment child) {
childRequestManagerFragments.remove(child);
}
/**
* Returns the set of fragments that this RequestManagerFragment's parent is a parent to. (i.e.
* our parent is the fragment that we are annotating).
*/
@Synthetic Set getDescendantRequestManagerFragments() {
if (rootRequestManagerFragment == null) {
return Collections.emptySet();
} else if (this.equals(rootRequestManagerFragment)) {
return Collections.unmodifiableSet(childRequestManagerFragments);
} else {
Set descendants = new HashSet<>();
for (SupportRequestManagerFragment fragment : rootRequestManagerFragment
.getDescendantRequestManagerFragments()) {
if (isDescendant(fragment.getParentFragmentUsingHint())) {
descendants.add(fragment);
}
}
return Collections.unmodifiableSet(descendants);
}
}
/**
* Sets a hint for which fragment is our parent which allows the fragment to return correct
* information about its parents before pending fragment transactions have been executed.
*/
void setParentFragmentHint(@Nullable Fragment parentFragmentHint) {
this.parentFragmentHint = parentFragmentHint;
if (parentFragmentHint != null && parentFragmentHint.getActivity() != null) {
registerFragmentWithRoot(parentFragmentHint.getActivity());
}
}
private Fragment getParentFragmentUsingHint() {
Fragment fragment = getParentFragment();
return fragment != null ? fragment : parentFragmentHint;
}
/**
* Returns true if the fragment is a descendant of our parent.
*/
private boolean isDescendant(Fragment fragment) {
Fragment root = this.getParentFragmentUsingHint();
Fragment parentFragment;
while ((parentFragment = fragment.getParentFragment()) != null) {
if (parentFragment.equals(root)) {
return true;
}
fragment = fragment.getParentFragment();
}
return false;
}
private void registerFragmentWithRoot(FragmentActivity activity) {
unregisterFragmentWithRoot();
rootRequestManagerFragment = Glide.get(activity).getRequestManagerRetriever()
.getSupportRequestManagerFragment(activity.getSupportFragmentManager(), null);
if (!this.equals(rootRequestManagerFragment)) {
rootRequestManagerFragment.addChildRequestManagerFragment(this);
}
}
private void unregisterFragmentWithRoot() {
if (rootRequestManagerFragment != null) {
rootRequestManagerFragment.removeChildRequestManagerFragment(this);
rootRequestManagerFragment = null;
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
registerFragmentWithRoot(getActivity());
} 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();
parentFragmentHint = null;
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();
}
@Override
public String toString() {
return super.toString() + "{parent=" + getParentFragmentUsingHint() + "}";
}
private class SupportFragmentRequestManagerTreeNode implements RequestManagerTreeNode {
@Synthetic
SupportFragmentRequestManagerTreeNode() { }
//获取当前隐藏fragment所有的RequestManager
@Override
public Set getDescendants() {
Set descendantFragments =
getDescendantRequestManagerFragments();
Set descendants = new HashSet<>(descendantFragments.size());
for (SupportRequestManagerFragment fragment : descendantFragments) {
if (fragment.getRequestManager() != null) {
descendants.add(fragment.getRequestManager());
}
}
return descendants;
}
@Override
public String toString() {
return super.toString() + "{fragment=" + SupportRequestManagerFragment.this + "}";
}
}
}
这个fragment还是比较简单的,介绍下几个比较重要的成员变量
- lifecycle : 保存着需要监听当前fragment或Activity的RequestManager,在隐藏fragment的生命周期改变时去通知保存的每一个RequestManager
- requestManagerTreeNode: 可以通过这个对象获取到在当前隐藏fragment里面的所有的RequestManager.
- childRequestManagerFragments: 当前隐藏fragment所有的子隐藏fragment的集合.
- rootRequestManagerFragment: 当前隐藏fragment的根隐藏fragment,就是Activity中第一个创建的隐藏fragment.
- parentFragmentHint: 当前隐藏fragment的父fragment.
接下来看下这个隐藏fragment是怎么通知Glide管理生命周期的,就拿onStart()方法分析
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
lifecycle的onStart()方法
void onStart() {
isStarted = true;
//通知每一个lifecycleListener
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStart();
}
}
lifecycleListener通过下面方法加入进来:
@Override
public void addListener(LifecycleListener listener) {
lifecycleListeners.add(listener);
if (isDestroyed) {
listener.onDestroy();
} else if (isStarted) {
listener.onStart();
} else {
listener.onStop();
}
}
我们来看下addListener()的调用位置:
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);//RequesManager实现了LifecycleListener这里就是将当前RequesManager
//加入lifecycle的管理中,典型的观察者模式,被观察者-----隐藏fragment生命周期调用,通过ActivityFragmentLifecycle通知
//每一个观察者RequesManager
}
lifecycle.addListener(connectivityMonitor);
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
glide.registerRequestManager(this);
}
这里的lifecycle就是ActivityFragmentLifecycle,在隐藏fragment创建的时候创建,并且在创建RequesManager的时候被传入.所以上面的lifecycleListener.onStart();就是调用RequesManager的onStart()方法:
/**
* 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 void onStart() {
resumeRequests();
targetTracker.onStart();
}
/**
* Restarts any loads that have not yet completed.
*
* @see #isPaused()
* @see #pauseRequests()
*/
public void resumeRequests() {
Util.assertMainThread();
requestTracker.resumeRequests();
}
RequestTracker: 跟踪request,负责对request取消,重新启动,暂停,运行等.
/**
* Starts any not yet completed or failed requests.
*/
public void resumeRequests() {
isPaused = false;
for (Request request : Util.getSnapshot(requests)) {
if (!request.isComplete() && !request.isCancelled() && !request.isRunning()) {
request.begin();//调用每个request的开始方法,这个方法就是加载的开始,上篇文章分析过
}
}
pendingRequests.clear();
}
那么request是怎么和RequestTracker联系起来的呢?
它们是在into()这个方法中关联起来的:
private > Y into(
@NonNull Y target,
@Nullable RequestListener targetListener,
@NonNull RequestOptions options) {
....省略...
options = options.autoClone();
Request request = buildRequest(target, targetListener, options);
Request previous = target.getRequest();
...省略...
requestManager.clear(target);
target.setRequest(request);
requestManager.track(target, request);//重点
return target;
}
RequestManager
void track(Target> target, Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
RequestTracker
/**
* Starts tracking the given request.
*/
public void runRequest(Request request) {
requests.add(request);//加入tracking集合
if (!isPaused) {
request.begin();
} else {
pendingRequests.add(request);
}
}
上面分析了onStart()方法,可以看出来Glide是在隐藏fragment的onStart()方法被调用时通过ActivityFragmentLifecycle通知每一个requestManager调用onStart(),随后调用RequestTracker的onStart()方法开启每一个RequestTracker跟踪的request的begin()方法开启或者继续加载.