1、前言
- 在
Android
开发中,加载图片的使用场景十分常见; - 过去,我们可能会自己写一个加载图片框架,自己设计请求网络操作、三级缓存功能,还能凑合使用;
- 如今,出现了大量的第三方图片加载框架,比如
Volley
、Picasso
、Glide
等,可谓是让开发者事半功倍; - 本篇文章,并不是介绍
Glide
图片加载库的使用步骤,而是对Glide
的设计流程、使用原理进行一个深度解剖;
2、源码解析
Glide.with(this).load("url").into(iv);
以上代码是使用Glide
最简单的写法,这样就成功的把一张图片加载到我们的控件上了,虽然说很简单,但是其内部代码到底做了怎样的操作,现在我们就一探究竟;
2.1、获取RequestManager对象
Glide.with(this);
public static RequestManager with(FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
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();
}
可以看到,调用with
方法是为了获取RequestManager
对象,那么如何获取RequestManger
对象呢?在内部调用getRetriever
方法,首先会获得一个RequestManagerRetriever
对象,这个对象的作用是为了创建RequestManger
对象的;要获取RequestManagerRetriever
对象,就要转到Glide
的getRequestManagerRetriever
方法中;
public static Glide get(Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
private static void checkAndInitializeGlide(Context context) {
// In the thread running initGlide(), one or more classes may call Glide.get(context).
// Without this check, those calls could trigger infinite recursion.
if (isInitializing) {
throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
+ " use the provided Glide instance instead");
}
isInitializing = true;
initializeGlide(context);
isInitializing = false;
}
Glide
使用了单例模式来维护,在checkAndInitializeGlide
方法中实例化glide
对象;
private static void initializeGlide(Context context) {
Context applicationContext = context.getApplicationContext();
···
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory() : null;
GlideBuilder builder = new GlideBuilder()
.setRequestManagerFactory(factory);
···
Glide glide = builder.build(applicationContext);
···
Glide.glide = glide;
}
在initializeGlide
方法中,通过建造者模式得到glide
对象;
public Glide build(Context context) {
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();//创建线程池
}
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
}
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();//创建bitmap池
bitmapPool = new LruBitmapPool(size);
}
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
if (memoryCache == null) {
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());//创建内存缓存
}
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
if (engine == null) {
engine = new Engine(memoryCache, diskCacheFactory, diskCacheExecutor, sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor());
}
RequestManagerRetriever requestManagerRetriever = new RequestManagerRetriever(
requestManagerFactory);//创建requestManagerRetriever对象
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock());//最终实例化Glide
}
在Build
方法里面,创建了requestManagerRetriever
对象,现在回到Glide
中;
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();
}
public RequestManagerRetriever getRequestManagerRetriever() {
return requestManagerRetriever;
}
随后获取requestManagerRetriever
对象,现在再回到with
方法中,看看是怎样获取到RequestManager
对象的;
public static RequestManager with(FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
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, null /*parentHint*/);
}
}
public RequestManager get(Fragment fragment) {
Preconditions.checkNotNull(fragment.getActivity(),
"You cannot start a load on a fragment before it is attached or after it is destroyed");
if (Util.isOnBackgroundThread()) {
return get(fragment.getActivity().getApplicationContext());
} else {
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getActivity(), fm, fragment);
}
}
public RequestManager get(Activity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm, null /*parentHint*/);
}
}
public RequestManager get(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());
}
// Support Fragments.
if (activity instanceof FragmentActivity) {
Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
if (fragment == null) {
return get(activity);
}
return get(fragment);
}
// Standard Fragments.
android.app.Fragment fragment = findFragment(view, activity);
if (fragment == null) {
return get(activity);
}
return get(fragment);
}
可以看到,get
方法提供了不一样的参数,有Context
、FragmentActivity
、Activity
、Fragment
、View
;根据不同的使用场景进行对应的方法选择;由于我传的是FragmentActivity
,所以选择该方法继续往下理解;
public RequestManager get(FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm = activity.getSupportFragmentManager();//获取Fragment管理器
return supportFragmentGet(activity, fm, null /*parentHint*/);
}
}
private RequestManager supportFragmentGet(Context context, FragmentManager fm,
Fragment parentHint) {
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);//实例化Fragment操作
RequestManager requestManager = current.getRequestManager();//从Fragment中获取RequestFragment对象
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
requestManager =
factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);//假如requestManager为null的话,就实例化一个放到该Fragment中
}
return requestManager;//最终返回RequestManager对象
}
SupportRequestManagerFragment getSupportRequestManagerFragment(
final FragmentManager fm, Fragment parentHint) {
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
current = new SupportRequestManagerFragment();//实例化一个Fragment
current.setParentFragmentHint(parentHint);
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();//加入到Fragment管理器中
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
从以上代码可知,首先从Activity
中获取了Fragment
管理器,然后新建一个SupportRequestManagerFragment
对象,其实它就是一个Fragment
对象,然后把Fragment
添加到fm
管理器中,与当前Activity
的生命周期进行绑定,这样的设计很巧妙,SupportRequestManagerFragment
对象管理着Glide
的生命周期,这样就能把Glide
生命周期和Activity
生命周期进行一个绑定,比如当Activity
处于后台状态时,Glide
就会停止加载或者Activity
销毁了Glide
也会销毁,这样能更好的节省流量、防止内存泄露等问题;最终从Fragment
对象中得到RequestManager
对象;然而说了那么多,RequestManager
对象到底有什么作用,实际上说白了,它的作用就是对Glide
图片加载请求进行一个管理;
2.2、构建RequestBuilder对象
load("url")
public RequestBuilder load(@Nullable Object model) {
return asDrawable().load(model);
}
public RequestBuilder asDrawable() {
return as(Drawable.class).transition(new DrawableTransitionOptions());
}
public RequestBuilder as(Class resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass);
}
public RequestBuilder load(@Nullable Object model) {
return loadGeneric(model);
}
private RequestBuilder loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
很简单,把Glide
对象和RequestManager
对象传入RequestBuilder
中,构建RequestBuilder
对象;
2.3、加载图片
into(iv);
public Target into(ImageView view) {
```
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
if (requestOptions.isLocked()) {
requestOptions = requestOptions.clone();
}
switch (view.getScaleType()) {
case CENTER_CROP:
requestOptions.optionalCenterCrop();
break;
case CENTER_INSIDE:
requestOptions.optionalCenterInside();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
requestOptions.optionalFitCenter();
break;
case FIT_XY:
requestOptions.optionalCenterInside();
break;
case CENTER:
case MATRIX:
default:
// Do nothing.
}
}
return into(context.buildImageViewTarget(view, transcodeClass));
}
在into方法里面,设置ImageView
控件的显示方式;
public Target buildImageViewTarget(ImageView imageView, Class transcodeClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
public Target buildTarget(ImageView view, Class clazz) {
if (Bitmap.class.equals(clazz)) {
return (Target) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (Target) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
根据传入的参数,设置BitmapImageViewTarget
对象;
public class BitmapImageViewTarget extends ImageViewTarget {
public BitmapImageViewTarget(ImageView view) {
super(view);
}
@Override
protected void setResource(Bitmap resource) {
view.setImageBitmap(resource);
}
}
以Bitmap
为例子,在该类里,就是把Bitmap
设置到ImageView
上,回到into
方法中;
public > Y into(@NonNull Y target) {
Util.assertMainThread();
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
Request previous = target.getRequest();
if (previous != null) {
requestManager.clear(target);
}
requestOptions.lock();
Request request = buildRequest(target);//构建请求体
target.setRequest(request);//把请求体设置到target中
requestManager.track(target, request);
return target;
}
假如该控件已经存在一个请求体,那么就移除掉,然后重新创建请求体,并且设置到控件Target
中,最终调用track
方法加载;
private Request buildRequest(Target target) {
return buildRequestRecursive(target, null, transitionOptions, requestOptions.getPriority(),
requestOptions.getOverrideWidth(), requestOptions.getOverrideHeight());
}
private Request buildRequestRecursive(Target target,
@Nullable ThumbnailRequestCoordinator parentCoordinator,
TransitionOptions, ? super TranscodeType> transitionOptions,
Priority priority, int overrideWidth, int overrideHeight) {
···
int thumbOverrideWidth = thumbnailBuilder.requestOptions.getOverrideWidth();
int thumbOverrideHeight = thumbnailBuilder.requestOptions.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !thumbnailBuilder.requestOptions.isValidOverride()) {
thumbOverrideWidth = requestOptions.getOverrideWidth();
thumbOverrideHeight = requestOptions.getOverrideHeight();
}
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest = obtainRequest(target, requestOptions, coordinator,
transitionOptions, priority, overrideWidth, overrideHeight);
isThumbnailBuilt = true;
// Recursively generate thumbnail requests.
Request thumbRequest = thumbnailBuilder.buildRequestRecursive(target, coordinator,
thumbTransitionOptions, thumbPriority, thumbOverrideWidth, thumbOverrideHeight);
isThumbnailBuilt = false;
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} else if (thumbSizeMultiplier != null) {
···
} else {
// Base case: no thumbnail.
return obtainRequest(target, requestOptions, parentCoordinator, transitionOptions, priority,
overrideWidth, overrideHeight);
}
}
private Request obtainRequest(Target target,
RequestOptions requestOptions, RequestCoordinator requestCoordinator,
TransitionOptions, ? super TranscodeType> transitionOptions, Priority priority,
int overrideWidth, int overrideHeight) {
requestOptions.lock();
return SingleRequest.obtain(
context,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
requestListener,
requestCoordinator,
context.getEngine(),
transitionOptions.getTransitionFactory());
}
根据设置指定的图片宽高进行加载,最终获取SingleRequest
对象;构建好后继续往下;
void track(Target> target, Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
public void track(Target> target) {
targets.add(target);
}
把Target
放到Set
集合中;以便统一管理;
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
pendingRequests.add(request);
}
}
调用begin
方法执行请求;
3、总结
- 在当前
Activity
中新建Fragment
并且与之相关联,让Glide
的生命周期和Activity
生命周期同步; - 可以自定义需要加载的图片宽高;