Glide源码分析-生命周期管理

基本概念

GlidePicasso有着基本一致的使用方法,最基本的使用方式如下:

1
2
3
4

Glide.with(Context/Activity/Fragment).load(url).into(view);

Picasso.with(Context).load(url).into(view);

但是我们从代码中能看到,Glide比较特殊的地方时可以传入ContextActivityFragment三种不同的对象作为上下文,这也是Glide第一个比较突出的特点,就是严格使用的话,加载图片的过程会绑定对应页面的生命周期,尽可能地提升加载效率。

生命周期绑定基本流程

生命周期绑定类设计图

相关类的介绍

  • Glide:总入口类,调用with(Context/Activity/Fragment)方法获取对应的RequestManager
  • RequestManagerRetriever:单例,根据Glide.with()方法传入的上下文构建RequestManager和对应的RequestManagerFragment并进行生命周期的绑定
  • RequestManagerFragment:一个无页面的Fragment,与Glide传入的Activity或者Fragment通过FragmentManager完成与加载请求生命周期的绑定,同时持有对应所有上下文的RequestManager,当生命周期改变时时回调对应的生命周期方法
  • LifecycleListener:生命周期回调接口,当对应的生命周期发生变化时收到通知
  • Lifecycle:生命周期接口,所有类型的RequestManagerFragment都持有该接口的实现类ActivityFragmentLifecycleRequestManagerFragment的生命周期发生变化时回调对应的方法
  • RequestManager:实现了LifecycleListener接口,收到生命周期变化回调时调用持有的Ruquest的对应方法

源码分析

只分析类的作用是不够的,不看代码根本解释不清楚。然后我们就以一个基本的Glide请求为例,看看在构建Request之前都发生了什么。
首先是Glide.with()方法,以Glide.with(fragment)为例

1
2
3
4
5

public static RequestManager with(Fragment fragment) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(fragment);
}

只看到是生成一个RequestManagerRetriever对象,然后调用对应的get(fragment)方法,那么我们再看这部分源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

private static final RequestManagerRetriever INSTANCE = new RequestManagerRetriever();

public static RequestManagerRetriever get() {
return INSTANCE;
}

public RequestManager get(Fragment fragment) {
if (fragment.getActivity() == null) {
throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
}
if (Util.isOnBackgroundThread()) {
return get(fragment.getActivity().getApplicationContext());
} else {
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getActivity(), fm);
}
}

首先get()方法很简单,就是一个单例模式。然后是get(fragment)方法,我们只看fragment可用的情况,这时候首先拿到那个fragment对应的FragmentManager,然后再返回supportFragmentGet方法,那么再看这部分源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

RequestManager supportFragmentGet(Context context, FragmentManager fm) {
//获取当前请求上下文对应FragmentManager内部用于绑定生命周期的RequestManagerFragment
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
//获取RequestManagerFragment内部绑定的RequestManager
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
//如果为空,则new一个RequestManager,并完成生命周期回调方法的互相绑定
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}

static final String FRAGMENT_TAG = "com.bumptech.glide.manager";

//以FragmentManager为key,RequestManagerFragment为value缓存用以绑定寿命周期的RequestManagerFragment,严格说这不是一个缓存,只是用来暂时保存已生成的还未被使用的RequestManagerFragment
final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
new HashMap<FragmentManager, SupportRequestManagerFragment>();

SupportRequestManagerFragment getSupportRequestManagerFragment(final FragmentManager fm) {
//先从FragmentManager根据TAG获取RequestManagerFragment
SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
//如果为空,再从pending缓存里获取
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
//如果为空,则生成一个新的RequestManagerFragment并add到对应的FragmentManager里
current = new SupportRequestManagerFragment();
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}

//当RequestManagerFragment被成功add之后从pending缓存中remove掉
@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;
removed = pendingSupportRequestManagerFragments.remove(supportFm);
break;
default:
handled = false;
}
if (handled && removed == null && Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Failed to remove expected request manager fragment, manager: " + key);
}
return handled;
}

这部分源码比较长,结合注释看容易理清楚。本质上就是根据传入的上下文对应的FragmentManager生成对应的RequestManagerRequestManagerFragment并完成互相绑定的过程,那么接下来就看生命周期绑定的过程,也是核心部分,首先看RequestManagerFragment的相关部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

public class SupportRequestManagerFragment extends Fragment {
private RequestManager requestManager;
private final ActivityFragmentLifecycle lifecycle;

public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}

// For testing only.
@SuppressLint("ValidFragment")
public SupportRequestManagerFragment(ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}

public void setRequestManager(RequestManager requestManager) {
this.requestManager = requestManager;
}

ActivityFragmentLifecycle getLifecycle() {
return lifecycle;
}

public RequestManager getRequestManager() {
return 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();
}

@Override
public void onLowMemory() {
super.onLowMemory();
// If an activity is re-created, onLowMemory may be called before a manager is ever set.
// See #329.
if (requestManager != null) {
requestManager.onLowMemory();
}
}

}

这部分源码删掉了不相关的代码,只看生命周期相关的方法。所以很明白,这个RequestManagerFragment继承自系统的Fragment,并持有对应的RequestManagerActivityFragmentLifecycle,当生命周期发生变化时会调用这两个对象对应的方法。然后我们再看ActivityFragmentLifecycle的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

class ActivityFragmentLifecycle implements Lifecycle {
private final Set<LifecycleListener> lifecycleListeners =
Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
private boolean isStarted;
private boolean isDestroyed;

@Override
public void addListener(LifecycleListener listener) {
lifecycleListeners.add(listener);
if (isDestroyed) {
listener.onDestroy();
} else if (isStarted) {
listener.onStart();
} else {
listener.onStop();
}
}

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();
}
}
}

也很简单,ActivityFragmentLifecycle实现了Lifecycle接口,持有一群(手动斜眼)lifecycleListener,当它的生命周期方法被调用时,也会调用所有lifecycleListener对应的方法。那么是谁把这些lifecycleListener给add进来,谁实现了这个接口,最终在收到生命周期变化的通知时做出处理呢?答案就在RequestManager里:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
this.context = context.getApplicationContext();
this.lifecycle = lifecycle;
this.treeNode = treeNode;
this.requestTracker = requestTracker;
this.glide = Glide.get(context);
this.optionsApplier = new OptionsApplier();

ConnectivityMonitor connectivityMonitor = factory.build(context,
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()) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
lifecycle.addListener(RequestManager.this);
}
});
} else {
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
}

刚才在RequestManagerRetriever的源码里我们知道了,在生成RequestManager时它会持有对应RequestManagerFragment内部的Lifecycle,当它的构造方法被调用时,同时会把自己给add进去,这时候生命周期已经完全绑定,RequestManager已经可以拿到对应所有请求的生命周期回调。细心的同学会发现还会add一个ConnectivityMonitor,这个就属于响应网络变化的优化工作了,有兴趣的同学可以看相关源码。然后我们再看回调方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

@Override
public void onStart() {
resumeRequests();
}

@Override
public void onStop() {
pauseRequests();
}

@Override
public void onDestroy() {
requestTracker.clearRequests();
}

这部分代码很容易明白了,就是在页面发生变化时,请求也随之响应,达到效率最大化。

总结

Ok,关于Glide请求的生命周期管理就基本分析完毕,Glide看起来跟Picasso用法基本一致,设计也类似,但是多出那么多方法并不凭空来的,单只是用一个不可见的Fragment实现了对一个上下文的ActivityFragment生命周期的监控,这部分的实现就非常巧妙。下一部分,我们继续分析 Glide构建Request完成后,接下来具体请求的过程。