Glide的with()方法和生命周期的源码分析
/** * Begin a load with Glide by passing in a context. * * @param context Any context, will not be retained. * @see #with(android.app.Activity) * @see #with(android.app.Fragment) * @see #with(androidx.fragment.app.Fragment) * @see #with(androidx.fragment.app.FragmentActivity) */@NonNullpublic static RequestManager with(@NonNull Context context) { return getRetriever(context).get(context);}@NonNullpublic static RequestManager with(@NonNull Activity activity) { return getRetriever(activity).get(activity);}@NonNullpublic static RequestManager with(@NonNull FragmentActivity activity) { return getRetriever(activity).get(activity);}@NonNullpublic static RequestManager with(@NonNull Fragment fragment) { return getRetriever(fragment.getContext()).get(fragment);}@SuppressWarnings("deprecation")@Deprecated@NonNullpublic static RequestManager with(@NonNull android.app.Fragment fragment) { return getRetriever(fragment.getActivity()).get(fragment);}@NonNullpublic static RequestManager with(@NonNull View view) { return getRetriever(view.getContext()).get(view);}
可以看到,with()方法的重载种类非常多,既可以传入Activity,也可以传入Fragment或者是Context。每一个with()方法重载的代码都非常简单,都是先调用getRetriever方法得到一个RequestManagerRetriever对象,然后再调用RequestManagerRetriever的实例get()方法,去获取RequestManager对象。
RequestManagerRetriever类中
@NonNull public RequestManager get(@NonNull Context context) { if (context == null) { throw new IllegalArgumentException("You cannot start a load on a null Context"); } == 如果不是Application 并且是在主线程的情况== 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 && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) { return get(((ContextWrapper) context).getBaseContext()); } } == Application 或者是在非主线程的情况 == return getApplicationManager(context); } @NonNull public RequestManager get(@NonNull FragmentActivity activity) { if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); } else { assertNotDestroyed(activity); FragmentManager fm = activity.getSupportFragmentManager(); return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity)); } } @NonNull public RequestManager get(@NonNull Fragment fragment) { Preconditions.checkNotNull( fragment.getContext(), "You cannot start a load on a fragment before it is attached or after it is destroyed"); if (Util.isOnBackgroundThread()) { return get(fragment.getContext().getApplicationContext()); } else { FragmentManager fm = fragment.getChildFragmentManager(); return supportFragmentGet(fragment.getContext(), fm, fragment, fragment.isVisible()); } } @SuppressWarnings("deprecation") @Deprecated @NonNull @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public RequestManager get(@NonNull android.app.Fragment fragment) { if (fragment.getActivity() == null) { throw new IllegalArgumentException( "You cannot start a load on a fragment before it is attached"); } if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { return get(fragment.getActivity().getApplicationContext()); } else { android.app.FragmentManager fm = fragment.getChildFragmentManager(); return fragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible()); } } @SuppressWarnings("deprecation") @NonNull public RequestManager get(@NonNull Activity activity) { if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); } else { assertNotDestroyed(activity); android.app.FragmentManager fm = activity.getFragmentManager(); return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity)); } } @SuppressWarnings("deprecation") @NonNull public RequestManager get(@NonNull View view) { if (Util.isOnBackgroundThread()) { return get(view.getContext().getApplicationContext()); } Preconditions.checkNotNull(view); Preconditions.checkNotNull( view.getContext(), "Unable to obtain a request manager for a view without a Context"); Activity activity = findActivity(view.getContext()); // The view might be somewhere else, like a service. if (activity == null) { return get(view.getContext().getApplicationContext()); } if (activity instanceof FragmentActivity) { Fragment fragment = findSupportFragment(view, (FragmentActivity) activity); return fragment != null ? get(fragment) : get((FragmentActivity) activity); } android.app.Fragment fragment = findFragment(view, activity); if (fragment == null) { return get(activity); } return get(fragment); }
上述代码虽然看上去逻辑有点复杂,但是将它们梳理清楚后还是很简单的。RequestManagerRetriever类中看似有很多个get()方法的重载,什么Context参数,Activity参数,Fragment参数等等,实际上只有两种情况而已,即传入Application类型的参数,和传入非Application类型的参数。
如果我们是在非主线程当中使用的Glide,那么不管你是传入的Activity还是Fragment,都会被强制当成Application来处理。 if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); }
我们先来看传入Application参数的情况。如果在Glide.with()方法中传入的是一个Application对象,那么这里就会调用带有Context参数的get()方法重载,然后会调用getApplicationManager()方法来获取一个RequestManager对象。其实这是最简单的一种情况,因为Application对象的生命周期即应用程序的生命周期,因此Glide并不需要做什么特殊的处理,它自动就是和应用程序的生命周期是同步的,如果应用程序关闭的话,Glide的加载也会同时终止。
接下来我们看传入非Application参数的情况。不管你在Glide.with()方法中传入的是Activity、FragmentActivity、v4包下的Fragment、还是app包下的Fragment,最终的流程都是一样的,那就是会向当前的Activity当中添加一个隐藏的Fragment。
那么这里为什么要添加一个隐藏的Fragment呢?因为Glide需要知道加载的生命周期。很简单的一个道理,如果你在某个Activity上正在加载着一张图片,结果图片还没加载出来,Activity就被用户关掉了,那么图片还应该继续加载吗?当然不应该。可是Glide并没有办法知道Activity的生命周期,于是Glide就使用了添加隐藏Fragment的这种小技巧,因为Fragment的生命周期和Activity是同步的,如果Activity被销毁了,Fragment是可以监听到的,这样Glide就可以捕获这个事件并停止图片加载了
分别对应的v4包和APP包下的两种Fragment的情况。supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity))fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity))
分析v4包下的,注释在代码中
@NonNull public RequestManager get(@NonNull FragmentActivity activity) { if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); } else { //这里是保证当前的FragmentActivity 或者是v4fragment attah 的FragmentActivity没有被销毁 assertNotDestroyed(activity); FragmentManager fm = activity.getSupportFragmentManager(); // 创建一个无ui的fragment return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity)); } }
supportFragmentGet方法中创建fragment的方法
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint, isParentVisible); == 这里的创建逻辑 首先通过tag来寻找是否创建过该fragment,如果没有的话,在 Map<FragmentManager,SupportRequestManagerFragment>pendingSupportRequestManagerFragments 中查询是否保存过,如果没有的话则创建一个无ui的fragment,并且保存到map中,并且如果acticity是 visible状态,则注册current.getGlideLifecycle().onStart(),然后在通过handler发送消息,将map 中的该fragment删除 @NonNull private SupportRequestManagerFragment getSupportRequestManagerFragment( @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) { SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); if (current == null) { current = pendingSupportRequestManagerFragments.get(fm); if (current == null) { current = new SupportRequestManagerFragment(); current.setParentFragmentHint(parentHint); if (isParentVisible) { current.getGlideLifecycle().onStart(); } pendingSupportRequestManagerFragments.put(fm, current); fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget(); } } return current; }
我们发现在创建fragment的时候会在构造方法中创建ActivityFragmentLifecycle 对象public class SupportRequestManagerFragment extends Fragment { private final ActivityFragmentLifecycle lifecycle; public SupportRequestManagerFragment() { this(new ActivityFragmentLifecycle()); } @VisibleForTesting @SuppressLint("ValidFragment") public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) { this.lifecycle = lifecycle; } @NonNull ActivityFragmentLifecycle getGlideLifecycle() { return lifecycle; } @Override public void onStart() { super.onStart(); lifecycle.onStart(); } @Override public void onStop() { super.onStop(); lifecycle.onStop(); } @Override public void onDestroy() { super.onDestroy(); lifecycle.onDestroy(); }}
ActivityFragmentLifecycle类是生命周期回调的管理类,它实现了LifeCycle接口,会将LifecycleListener的接口加入到ActivityFragmentLifecycle类中的Set集合中,当SupportRequestManagerFragment的生命周期的方法触发时,会调用ActivityFragmentLifeCycle的相应方法。主要保存了isStarted和isDestroyed变量,并提供了addListener和removeListener方法,如果想获取到生命周期的回调,只需调用addListener()方法注册即可。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(@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(); } }}
更多相关文章
- Android中利用Intent传递数据到另一个页面
- android更新UI的几种方法
- android TelephonyManager类的方法
- Android方法的传递值及其改变
- android中的定时器
- 【Android】播放视频的简易播放器源码
- Android(安卓)Http请求失败解决方法
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用