Glide基本使用方式:Glide.with(context).load(url).into(imageView);
Glide 最基本的用法就是三步走:先with(),再load(),最后into()。
那么我们开始一步步阅读这三步走的源码,先从with()看起。
1. with()
with()方法是Glide 类中的一组静态方法,它有好几个方法重载,我们来看一下Glide 类中所
有with()方法的方法重载:
public class Glide {
...
public static RequestManager with(Context context) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(context);
}
public static RequestManager with(Activity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
public static RequestManager with(FragmentActivity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static RequestManager with(android.app.Fragment fragment) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(fragment);
}
public static RequestManager with(Fragment fragment) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(fragment);
}
}
可以看到,with()方法的重载种类非常多,既可以传入Activity,也可以传入Fragment 或者
是Context。每一个with()方法重载的代码都非常简单,都是先调用RequestManagerRetriever
的静态get()方法得到一个RequestManagerRetriever 对象,这个静态get()方法就是一个单例
实现,没什么需要解释的。然后再调用RequestManagerRetriever 的实例get()方法,去获取
RequestManager 对象。
而RequestManagerRetriever 的实例get()方法中的逻辑是什么样的呢?我们一起来看一看:
public class RequestManagerRetriever implements Handler.Callback {
private static final RequestManagerRetriever INSTANCE = new RequestManagerRetriever();
private volatile RequestManager applicationManager;
...
/**
* Retrieves and returns the RequestManagerRetriever singleton.
*/
public static RequestManagerRetriever get() {
return INSTANCE;
}
private RequestManager getApplicationManager(Context context) {
// Either an application context or we're on a background thread.
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
// Normally pause/resume is taken care of by the fragment we add to
the fragment or activity.
// However, in this case since the manager attached to the application
will not receive lifecycle
// events, we must force the manager to start resumed using
ApplicationLifecycle.
applicationManager = new
RequestManager(context.getApplicationContext(),
new ApplicationLifecycle(), new
EmptyRequestManagerTreeNode());
}
}
}
return applicationManager;
}
public RequestManager get(Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
} 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) {
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}
public RequestManager get(FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm);
}
}
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);
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public RequestManager get(Activity activity) {
if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT <
Build.VERSION_CODES.HONEYCOMB) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm);
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private static void assertNotDestroyed(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 &&
activity.isDestroyed()) {
throw new IllegalArgumentException("You cannot start a load for a destroyed
activity");
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public RequestManager get(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);
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
RequestManagerFragment getRequestManagerFragment(final
android.app.FragmentManager fm) {
RequestManagerFragment current = (RequestManagerFragment)
fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
current = new RequestManagerFragment();
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current,
FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER,
fm).sendToTarget();
}
}
return current;
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
RequestManagerFragment current = getRequestManagerFragment(fm);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
requestManager = new RequestManager(context, current.getLifecycle(),
current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
SupportRequestManagerFragment getSupportRequestManagerFragment(final
FragmentManager fm) {
SupportRequestManagerFragment current = (SupportRequestManagerFragment)
fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
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;
}
RequestManager supportFragmentGet(Context context, FragmentManager fm) {
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(fm);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
requestManager = new RequestManager(context, current.getLifecycle(),
current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
...
}
上述代码虽然看上去逻辑有点复杂, 但是将它们梳理清楚后还是很简单的。
RequestManagerRetriever 类中看似有很多个get()方法的重载,什么Context 参数,Activity
参数,Fragment 参数等等,实际上只有两种情况而已,即传入Application 类型的参数,和
传入非Application 类型的参数。
我们先来看传入Application 参数的情况。如果在Glide.with()方法中传入的是一个Application
对象,那么这里就会调用带有Context 参数的get()方法重载,然后会在第44 行调用
getApplicationManager()方法来获取一个RequestManager 对象。其实这是最简单的一种情况,
因为Application 对象的生命周期即应用程序的生命周期,因此Glide 并不需要做什么特殊的
处理,它自动就是和应用程序的生命周期是同步的,如果应用程序关闭的话,Glide 的加载
也会同时终止。
接下来我们看传入非Application 参数的情况。不管你在Glide.with()方法中传入的是Activity、
FragmentActivity、v4 包下的Fragment、还是app 包下的Fragment,最终的流程都是一样的,
那就是会向当前的Activity 当中添加一个隐藏的Fragment。具体添加的逻辑是在上述代码的
第117 行和第141 行,分别对应的app 包和v4 包下的两种Fragment 的情况。那么这里为什
么要添加一个隐藏的Fragment 呢?因为Glide 需要知道加载的生命周期。很简单的一个道理,
如果你在某个Activity 上正在加载着一张图片,结果图片还没加载出来,Activity 就被用户关
掉了,那么图片还应该继续加载吗?当然不应该。可是Glide 并没有办法知道Activity 的生
命周期,于是Glide 就使用了添加隐藏Fragment 的这种小技巧,因为Fragment 的生命周期
和Activity 是同步的,如果Activity 被销毁了,Fragment 是可以监听到的,这样Glide 就可以
捕获这个事件并停止图片加载了。
这里额外再提一句,从第48 行代码可以看出,如果我们是在非主线程当中使用的Glide,那
么不管你是传入的Activity 还是Fragment,都会被强制当成Application 来处理。不过其实这
就属于是在分析代码的细节了。文章来源:https://www.toymoban.com/news/detail-427877.html
总体来说, 第一个with() 方法的源码还是比较好理解的。其实就是为了得到一个
RequestManager 对象而已,然后Glide 会根据我们传入with()方法的参数来确定图片加载的
生命周期,并没有什么特别复杂的逻辑。文章来源地址https://www.toymoban.com/news/detail-427877.html
到了这里,关于Glide图片加载框架是如何确定图片加载的生命周期的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!