你一定听过Glide的优势之一是能够感知生命周期,从而暂停加载、回收资源等
这里首先简述原理,通过构建一个空白的fragment,然后将这个fragment添加到Activity上,此时fragment便有了生命周期的感知能力。然后再想办法将这个感知信号传递到每个需要的地方即可。
那接下来具体看下是如何实现的这些过程的。
观察者模式
Lifecycle
可以理解成被观察者,抽象成具有生命周期的组件,接纳观察者
public interface Lifecycle {
void addListener(@NonNull LifecycleListener listener);
void removeListener(@NonNull LifecycleListener listener);
}
LifecycleListener
定义观察者能够感知到哪些生命周期信号
public interface LifecycleListener {
void onStart();
void onStop();
void onDestroy();
}
那现在其实还差个通知观察者的具体实现
这里根据 Glide.with(context)
传入的context类型不同,分为两种类型的生命周期。
- ActivityFragmentLifecycle
- ApplicationLifecycle
ActivityFragmentLifecycle
class ActivityFragmentLifecycle implements Lifecycle {
// 注释1
private final Set<LifecycleListener> lifecycleListeners =
Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
private boolean isStarted;
private boolean isDestroyed;
@Override
public void addListener(@NonNull LifecycleListener listener) {
lifecycleListeners.add(listener);
// 注释2
if (isDestroyed) {
listener.onDestroy();
} else if (isStarted) {
listener.onStart();
} else {
listener.onStop();
}
}
@Override
public void removeListener(@NonNull LifecycleListener listener) {
lifecycleListeners.remove(listener);
}
// 注释3
void onStart() {
isStarted = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStart();
}
}
// 注释4
void onStop() {
isStarted = false;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStop();
}
}
// 注释5
void onDestroy() {
isDestroyed = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onDestroy();
}
}
}
- 注释1 用Set集合保存所有的观察者
LifecycleListener
- 注释2 这里是实现粘性事件特点,让后来的观察者及时收到当前最新的生命周期
- 注释3、注释4、注释5 定义各个生命周期方法,从而循环通知观察者
以上生命周期通知框架基本定义好了,那在哪里真的感知的然后通知的?
RequestManagerFragment
这里通过组合模式实现了生命周期的感知
public class RequestManagerFragment extends Fragment {
private static final String TAG = "RMFragment";
private final ActivityFragmentLifecycle lifecycle;
public RequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
@VisibleForTesting
@SuppressLint("ValidFragment")
RequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
/**
* Sets the current {@link com.bumptech.glide.RequestManager}.
*
* @param requestManager The request manager to use.
*/
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 exists. */
@Nullable
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();
unregisterFragmentWithRoot();
}
}
接着看下这个fragment是什么时候创建并添加到FragmentManager
的
RequestManagerRetriever#getRequestManagerFragment
@SuppressWarnings("deprecation")
@VisibleForTesting
// 注释1
final Map<android.app.FragmentManager, RequestManagerFragment> pendingRequestManagerFragments =
new HashMap<>();
@SuppressWarnings("deprecation")
@NonNull
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm, @Nullable android.app.Fragment parentHint) {
// If we have a pending Fragment, we need to continue to use the pending Fragment. Otherwise
// there's a race where an old Fragment could be added and retrieved here before our logic to
// add our pending Fragment notices. That can then result in both the pending Fragmeng and the
// old Fragment having requests running for them, which is impossible to safely unwind.
// 注释2
RequestManagerFragment current = pendingRequestManagerFragments.get(fm);
if (current == null) {
// 注释3
current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
pendingRequestManagerFragments.put(fm, current);
// 注释4
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
// 注释5
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
- 注释1 这里用 Map 来保存 fragment,达到复用
- 注释2 如果map中已经有fragment,直接复用
- 注释3 如果map中没有,尝试通过FragmentManager直接去查Fragment是否已经绑定,如果绑定就无需重复了。
- 注释4 将新的fragment添加到页面上,从而达到感知到生命周期,这个添加的过程是异步的
- 注释5 检查fragment是否添加成功或者添加失败,如果添加成功,就从Map中移除 (清理缓存)
假如同时有多处调用该方法,所以在前面new 出来一个RequestManagerFragment,随后就把它放到pendingRequestManagerFragments中,那么task2再进来的时候从缓存中能取到,就不会再重新new和add了。
那么下一个问题来了,为什么会出现下面这行代码,add后又需要马上发一个消息remove掉?在前面阻止掉task2重复new和add的操作后,就把这个缓存删掉,可以避免内存泄漏和内存压力
因为这个时候已经添加完毕,下个任务到来的时候可以直接从fm中查找到。
到这里,整个系统运转过程就差具体的观察者了,我们需要再看,以至于更好的理解Glide感知到生命周期后的策略。
RequestManagerRetriever#fragmentGet
private RequestManager fragmentGet(
@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
// 注释1
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
// 注释2
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
// This is a bit of hack, we're going to start the RequestManager, but not the
// corresponding Lifecycle. It's safe to start the RequestManager, but starting the
// Lifecycle might trigger memory leaks. See b/154405040
if (isParentVisible) {
requestManager.onStart();
}
// 注释3
current.setRequestManager(requestManager);
}
return requestManager;
}
- 这个方法返回
RequestManger
,负责处理图片加载请求并管理加载过程中的生命周期和资源 - 注释1 如果fragment中已经绑定了
RequestManager
,直接返回 - 注释2 未绑定,就先创建一个
RequestManager
,也就是在这个里面注册的观察者,后面看 - 注释3 将这个
RequestManager
和 fragment 绑定
RequestManagerFactory
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) {
// 注释1
return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
}
};
}
- 如果Glie 外面不做配置,默认使用的
DEFAULT_FACTORY
- 注释1 这里lifecyle就是我们在
RequestManagerFragment
中通过组合模式引入的ActivityFragmentLifecycle
RequestManager#构造方法
这里我们关注 拿到这个Lifecycle 后 都注册了哪些观察者
public class RequestManager implements LifecycleListener,... {
...
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()) {
Util.postOnUiThread(addSelfToLifecycle);
} else {
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
...
}
private final Runnable addSelfToLifecycle =
new Runnable() {
@Override
public void run() {
lifecycle.addListener(RequestManager.this);
}
};
...
}
总共有两处
- 将当前
RequestManager
注册成观察者,这样当收到生命周期感知后来暂停和恢复请求(本文不详细讨论),同时也会将信号转发到各个Target
,下面会具体看如何转发的 - 将网络监听器注册成观察者,通过监听生命周期来完成广播的注册和反注册
RequestManager#生命周期方法
@GuardedBy("this")
private final TargetTracker targetTracker = new TargetTracker();
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
@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);
Util.removeCallbacksOnUiThread(addSelfToLifecycle);
glide.unregisterRequestManager(this);
}
- 管理
Request
:在对应的生命周期中,开始请求、暂停请求、移除请求监听 - 管理
Target
:收到生命周期回调后,又通过 TargetTracker 进行了转发,进而管理每个Target
TargetTracker
- 至于
TargetTracker
什么时候关联的Target,这里不做讨论track
- 可以看到 每个Target 也实现了
LifecycleListener
,这里又是一个新的观察者模式
public final class TargetTracker implements LifecycleListener {
private final Set<Target<?>> targets =
Collections.newSetFromMap(new WeakHashMap<Target<?>, Boolean>());
public void track(@NonNull Target<?> target) {
targets.add(target);
}
public void untrack(@NonNull Target<?> target) {
targets.remove(target);
}
@Override
public void onStart() {
for (Target<?> target : Util.getSnapshot(targets)) {
target.onStart();
}
}
@Override
public void onStop() {
for (Target<?> target : Util.getSnapshot(targets)) {
target.onStop();
}
}
@Override
public void onDestroy() {
for (Target<?> target : Util.getSnapshot(targets)) {
target.onDestroy();
}
}
@NonNull
public List<Target<?>> getAll() {
return Util.getSnapshot(targets);
}
public void clear() {
targets.clear();
}
}
网友评论