内容简介:图片加载时只需调用以下代码,其中包含应用进入后台,图片会暂停加载的策略。通过这篇文章,探究上面的
图片加载时只需调用以下代码, Glide 就会全自动完成下载、缓存、缩放、展示等流程。
Glide.with(this) .load("http://www.abc.com") .into(imageView)
其中包含应用进入后台,图片会暂停加载的策略。通过这篇文章,探究 Glide 是如何实现开发者不主动触发逻辑,就能达到任务生命周期自动管理的奥秘。
Glide
上面的 Glide.with(this)
根据传入实参类型,例如: FragmentActivity 、 Fragment 、 Context 等不同选择目标重载方法。这里选择 FragmentActivity 进行解析,因为 AppCompatActivity 的父类是 FragmentActivity 。
public static RequestManager with(@NonNull FragmentActivity activity) { return getRetriever(activity).get(activity); }
先获取 Glide 单例,然后从这个单例里获取 RequestManagerRetriever 的实例。
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(); }
RequestManagerRetriever
忽略 Glide 首次初始化流程,终于从 RequestManagerRetriever 获取 RequestManager 实例。
public RequestManager get(@NonNull FragmentActivity activity) { // 前后台判断 if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); } else { assertNotDestroyed(activity); // 从Activity实例获取FragmentManager FragmentManager fm = activity.getSupportFragmentManager(); return supportFragmentGet(activity, fm, null, isActivityVisible(activity)); } }
从上面可见,条件判断语句根据应用是否在前台走分支。因为本文关心是应用在前台的逻辑,所以直接走 else 。
进入分支后可见从 Activity 实例获取 FragmentManager 。
private RequestManager supportFragmentGet( @NonNull Context context, @NonNull FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) { // 看下文 SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint, isParentVisible); RequestManager requestManager = current.getRequestManager(); if (requestManager == null) { Glide glide = Glide.get(context); requestManager = factory.build( glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context); current.setRequestManager(requestManager); } return requestManager; }
以下方法从 Activity 的 FragmentManager 中查找是否存在名为 FRAGMENT_TAG 的 Fragment 实例。这个实例相当于一个隐形的钩子,挂在 Activity 监听界面生命周期变化,并回调 Glide 图片加载策略。
static final String FRAGMENT_TAG = "com.bumptech.glide.manager";
实例不存在就创建 Fragment 实例,这个实例类型为 SupportRequestManagerFragment 。
private SupportRequestManagerFragment getSupportRequestManagerFragment( @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) { SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); // 判断实例为空则需构建Fragment实例并加入到Activity if (current == null) { // 用FragmentManager获取SupportRequestManagerFragment实例 current = pendingSupportRequestManagerFragments.get(fm); if (current == null) { // 创建新实例 current = new SupportRequestManagerFragment(); current.setParentFragmentHint(parentHint); // Activity可见,触发Fragment的onStart()逻辑调用 if (isParentVisible) { current.getGlideLifecycle().onStart(); } pendingSupportRequestManagerFragments.put(fm, current); // 把SupportRequestManagerFragment加入到Activity的FragmentManager中 fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget(); } } return current; }
所有创建的 SupportRequestManagerFragment 都保存在以下哈希表中
final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments = new HashMap<>();
SupportRequestManagerFragment
接下来看看上面提及的 SupportRequestManagerFragment 。从签名可知继承父类 Fragment ,但不像一般 Fragment 包含填充的UI界面,而是仅包含生命周期的相关回调操作。说白了,就是借用 Fragment 达到监听 Activity 生命周期的目标。
public class SupportRequestManagerFragment extends Fragment { // 生命周期回调 private final ActivityFragmentLifecycle lifecycle; private final RequestManagerTreeNode requestManagerTreeNode = new SupportFragmentRequestManagerTreeNode(); private final Set<SupportRequestManagerFragment> childRequestManagerFragments = new HashSet<>(); @Nullable private SupportRequestManagerFragment rootRequestManagerFragment; @Nullable private RequestManager requestManager; @Nullable private Fragment parentFragmentHint; public SupportRequestManagerFragment() { this(new ActivityFragmentLifecycle()); } @VisibleForTesting @SuppressLint("ValidFragment") public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) { this.lifecycle = lifecycle; } ..... @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. } } // 注意下面不同生命周期对lifecycle的调用 @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(); } }
ActivityFragmentLifecycle
最后进入 ActivityFragmentLifecycle 实现类,这个类其实就是观察者模式的具体实现。所有需要加载图片的任务,自行创建 LifecycleListener 放入 ActivityFragmentLifecycle 中。
class ActivityFragmentLifecycle implements Lifecycle { // 监听器集合 private final Set<LifecycleListener> lifecycleListeners = Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>()); private boolean isStarted; private boolean isDestroyed; // 把给定的监听器添加到监听器列表,以便接收生命周期事件的通知 // 最新的生命周期事件会在所有注册的监听器上触发 // 若activity或fragment被stop,会调用LifecycleListener.onStop() // onStart和onDestroy生命周期有类似操作 @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(); } } }
最后,定制的 Fragment 监听 Activity 生命周期变化,告知 ActivityFragmentLifecycle ,随后 ActivityFragmentLifecycle 回调所有注册的监听器,实现应用进入后台暂停加载等功能。
总结
通过上述流程可知, Glide 的图片加载生命周期管理依赖传入的实例。
如果实例类型为 Activity , Glide 就能向里面注册一个没有界面的 Fragment 达到监听生命周期变化的目的。所以,该参数应尽可能传入 Activity 或 Fragment 对象,最少也得是 View 持有的 Context ,而不是 ApplicationContext 。
最后, Glide 监听界面生命周期变化没有什么奥秘,就是把定制的 Fragment 添加到图片所在的 Activity 中,利用系统机制监听周期变化,在不同周期的不同加载操作。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。