Glide源码学习
前言
开始
基本使用非常简单,链式调用把context对象传入,设置要加载的URL,设置要填充的ImageView控件,方法很简洁,每次都是传入的最核心的参数,底层加载的缓存逻辑,加载的引擎,加载的对象的适配,URL的适配…都为我们做了封装。使用者无需关心这些细节就可以实现图片的加载。这才是优秀的库该有的样子足够简洁,但是足够强大。把复杂留给自己,把简单留给用户。
Glide.with(fragment).load(myUrl).into(imageView);
With方法
前面看了Glide的基本使用,Glide是外观类,我们先看前面例子中的with方法
with相关的重载方法有四个,最终都是返回一个RequestManager,后面调用load方法用的就是返回的RequestManager。
@NonNull
public static RequestManager with(@NonNull Context context) {return getRetriever(context).get(context);
}@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {return getRetriever(activity).get(activity);
}@NonNull
public static RequestManager with(@NonNull Fragment fragment) {return getRetriever(fragment.getContext()).get(fragment);
}@NonNull
public static RequestManager with(@NonNull View view) {return getRetriever(view.getContext()).get(view);
}
都是先调用getRetriever(),getRetriever()方法是Glide的静态方法,会返回一个RequestManagerRetriever。这个方法中会引出Glide的构造,最终通过调用Glide实例的getRequestManagerRetriever方法返回RequestManagerRetriever。
@NonNull
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, DESTROYED_ACTIVITY_WARNING);return Glide.get(context).getRequestManagerRetriever();
}//双重校验锁单例模式获取Glide,glide实例是被volatile修饰
@NonNull
// Double checked locking is safe here.
@SuppressWarnings("GuardedBy")
public static Glide get(@NonNull Context context) {if (glide == null) {//这里通过反射创建一个GeneratedAppGlideModuleImpl的实例GeneratedAppGlideModule annotationGeneratedModule =getAnnotationGeneratedGlideModules(context.getApplicationContext());synchronized (Glide.class) {if (glide == null) {//检查是否初始化过GlidecheckAndInitializeGlide(context, annotationGeneratedModule);}}}return glide;}
继续看checkAndInitializeGlide方法,检查并初始化Glide
static void checkAndInitializeGlide(@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {// In the thread running initGlide(), one or more classes may call Glide.get(context).//初始化中,其他类也可能调用Glide.get// Without this check, those calls could trigger infinite recursion.//如果没有这个校验,有可能触发无线递归if (isInitializing) {throw new IllegalStateException("Glide has been called recursively, this is probably an internal library error!");}//标记正在初始化中isInitializing = true;try {initializeGlide(context, generatedAppGlideModule);} finally {//标记初始化中为falseisInitializing = false;}}@GuardedBy("Glide.class")private static void initializeGlide(@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {//新建一个GlideBuilder传入initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);}private static void initializeGlide(@NonNull Context context,@NonNull GlideBuilder builder,@Nullable GeneratedAppGlideModule annotationGeneratedModule) {//获取getApplicationContext,这里我们要知道构造Glide是全局唯一的Context applicationContext = context.getApplicationContext();List<GlideModule> manifestModules = Collections.emptyList();//GlideModule相关处理,先忽略...RequestManagerRetriever.RequestManagerFactory factory =annotationGeneratedModule != null? annotationGeneratedModule.getRequestManagerFactory(): null;builder.setRequestManagerFactory(factory);for (GlideModule module : manifestModules) {module.applyOptions(applicationContext, builder);}if (annotationGeneratedModule != null) {annotationGeneratedModule.applyOptions(applicationContext, builder);}//构造GlideGlide glide = builder.build(applicationContext, manifestModules, annotationGeneratedModule);//注册ComponentCallbackapplicationContext.registerComponentCallbacks(glide);Glide.glide = glide;}
这里注意在initializeGlide方法中用的是applicationContext,不依赖某个Activity,Service,Fragment等。为什么提一下这个,因为后面RequestManager的生成不是这样的,后面做下区分。
@NonNullGlide build(@NonNull Context context,List<GlideModule> manifestModules,AppGlideModule annotationGeneratedGlideModule) {//设置资源执行器if (sourceExecutor == null) {sourceExecutor = GlideExecutor.newSourceExecutor();}//设置磁盘缓存执行器if (diskCacheExecutor == null) {diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();}//设置动画执行器if (animationExecutor == null) {animationExecutor = GlideExecutor.newAnimationExecutor();}//设置内存计算器if (memorySizeCalculator == null) {memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();}//设置连接监控工厂if (connectivityMonitorFactory == null) {connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();}//构造Bitmap复用池if (bitmapPool == null) {int size = memorySizeCalculator.getBitmapPoolSize();if (size > 0) {bitmapPool = new LruBitmapPool(size);} else {bitmapPool = new BitmapPoolAdapter();}}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(),animationExecutor,isActiveResourceRetentionAllowed);}if (defaultRequestListeners == null) {defaultRequestListeners = Collections.emptyList();} else {defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);}GlideExperiments experiments = glideExperimentsBuilder.build();//新建一个RequestManagerRetriever//这里注意后面load方法会用到这个requestManagerRetriever来获取RequestManagerRequestManagerRetriever requestManagerRetriever =new RequestManagerRetriever(requestManagerFactory);//构造Glide,传入以上实例作为参数return new Glide(context,engine,memoryCache,bitmapPool,arrayPool,requestManagerRetriever,connectivityMonitorFactory,logLevel,defaultRequestOptionsFactory,defaultTransitionOptions,defaultRequestListeners,manifestModules,annotationGeneratedGlideModule,experiments);}
构造方法
Glide(@NonNull Context context,@NonNull Engine engine,@NonNull MemoryCache memoryCache,@NonNull BitmapPool bitmapPool,@NonNull ArrayPool arrayPool,@NonNull RequestManagerRetriever requestManagerRetriever,@NonNull ConnectivityMonitorFactory connectivityMonitorFactory,int logLevel,@NonNull RequestOptionsFactory defaultRequestOptionsFactory,@NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,@NonNull List<RequestListener<Object>> defaultRequestListeners,@NonNull List<GlideModule> manifestModules,@Nullable AppGlideModule annotationGeneratedModule,@NonNull GlideExperiments experiments) {this.engine = engine;this.bitmapPool = bitmapPool;this.arrayPool = arrayPool;this.memoryCache = memoryCache;this.requestManagerRetriever = requestManagerRetriever;this.connectivityMonitorFactory = connectivityMonitorFactory;this.defaultRequestOptionsFactory = defaultRequestOptionsFactory;// This has a circular relationship with Glide and GlideContext in that it depends on both,// but it's created by Glide's constructor. In practice this shouldn't matter because the// supplier holding the registry should never be initialized before this constructor finishes.GlideSupplier<Registry> registry =RegistryFactory.lazilyCreateAndInitializeRegistry(this, manifestModules, annotationGeneratedModule);ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();//新建一个GlideContext,并传递大部分构造方法的参数进去glideContext =new GlideContext(context,arrayPool,registry,imageViewTargetFactory,defaultRequestOptionsFactory,defaultTransitionOptions,defaultRequestListeners,engine,experiments,logLevel);}
现在getRetriever()方法基本看完,核心就是为我们构造出了Glide单例,然后调用Glide的getRequestManagerRetriever()得到RequestManagerRetriever
@NonNull
public RequestManagerRetriever getRequestManagerRetriever() {return requestManagerRetriever;
}
这个requestManagerRetriever在Glide构造方法的时候看到过,构造的时候,新建并传递了requestManagerRetriever参数。现在让我们回退再回到with方法,先通过getRetriever方法得到一个RequestManagerRetriever,然后调用它的get方法。下面去看RequestManagerRetriever的get方法,get方法主要是获取一个RequestManager。基本上跟Glide的with方法一一对应,不一样的是with方法最终都调用到了一个方法,而这个get实现都有些区别。
@NonNull
public RequestManager get(@NonNull Context context) {...}@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {...}@NonNull
public RequestManager get(@NonNull Fragment fragment) {...}@NonNull
public RequestManager get(@NonNull View view) {...}
上面这四种,第四种其实是分情况如果找到这个View的Activity,Activity是否是属于FragmentActivity,是FragmentActivity的话是否是属于Fragment等最终是调用前三种的一个,所以主要分为三种类型:
- 参数为FragmentActivity
- 参数为Fragment
- 参数为Context
参数为FragmentActivity
public RequestManager get(@NonNull FragmentActivity activity) {...//是否可见boolean isActivityVisible = isActivityVisible(activity);//获取Glide单例Glide glide = Glide.get(activity.getApplicationContext());//调用lifecycleRequestManagerRetriever的getOrCreatereturn lifecycleRequestManagerRetriever.getOrCreate(activity,glide,activity.getLifecycle(),activity.getSupportFragmentManager(),isActivityVisible);}
lifecycleRequestManagerRetriever是在RequestManagerRetriever构造方法中新建的,也就意味着Glide单例新建之前已经构造好了lifecycleRequestManagerRetriever实例。
注意第三个参数是getLifecycle,只有ComponentActivity才有这个方法,Activity中是没有这个方法的,这也就是为什么这个参数传入的不是Activity的原因。通过这个Lifecycle可以监控activity的生命周期。也就能及时回收,避免发生内存泄露。
接着看getOrCreate
RequestManager getOrCreate(Context context,Glide glide,final Lifecycle lifecycle,FragmentManager childFragmentManager,boolean isParentVisible) {//断言在主线程,不在的话抛异常Util.assertMainThread();//看名字大概是根据lifecycle为key,获取唯一的RequestManagerRequestManager result = getOnly(lifecycle);if (result == null) {//LifecycleLifecycle这名字起的。。其实是它实现了glide自己的Lifecycle//同时又实现了Android的LifecycleObserverLifecycleLifecycle glideLifecycle = new LifecycleLifecycle(lifecycle);//构造一个新的result =factory.build(glide,glideLifecycle,new SupportRequestManagerTreeNode(childFragmentManager),context);//存放到lifecycleToRequestManager这个Map中lifecycleToRequestManager.put(lifecycle, result);glideLifecycle.addListener(new LifecycleListener() {@Overridepublic void onStart() {}@Overridepublic void onStop() {}@Overridepublic void onDestroy() {lifecycleToRequestManager.remove(lifecycle);}});// 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/154405040if (isParentVisible) {//如果Parent可见,直接执行onStart()方法result.onStart();}}//返回RequestManagerreturn result;}
接着看RequestManager的构建,这里使用的是工厂模式,factory是LifecycleRequestManagerRetriever构造的时候传入的,LifecycleRequestManagerRetriever的构造是在RequestManagerRetriever的构造方法中,也就是Glide构造之前。RequestManagerRetriever的构造方法中传入了factory,为空的话会使用DEFAULT_FACTORY,什么时候不为空呢,就是在initializeGlide方法中annotationGeneratedModule.getRequestManagerFactory()不为空,这里先不深入,我们直接看DEFAULT_FACTORY。
private static final RequestManagerFactory DEFAULT_FACTORY =new RequestManagerFactory() {@NonNull@Overridepublic RequestManager build(@NonNull Glide glide,@NonNull Lifecycle lifecycle,@NonNull RequestManagerTreeNode requestManagerTreeNode,@NonNull Context context) {直接new了一个RequestManagerreturn new RequestManager(glide, lifecycle, requestManagerTreeNode, context);}};
最终调用到
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));// Order matters, this might be unregistered by teh listeners below, so we need to be sure to// register first to prevent both assertions and memory leaks.glide.registerRequestManager(this);// 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);defaultRequestListeners =new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());}
参数为Fragment
基本同参数为FragmentActivity,不同的是lifecycle这里获取的是fragment.getLifecycle(),感兴趣的可以自行查阅源码
参数为Context
public RequestManager get(@NonNull 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 ContextWrapper// Only unwrap a ContextWrapper if the baseContext has a non-null application context.// Context#createPackageContext may return a Context without an Application instance,// in which case a ContextWrapper may be used to attach one.&& ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {return get(((ContextWrapper) context).getBaseContext());}}return getApplicationManager(context);}
到这里我们了解了RequestManager的生成过程。
总结:With阶段主要为:
- 获取RequestManagerRetriever,获取过程中若未构建Glide,帮我们构建好Glide单例
- 有了RequestManagerRetriever,通过RequestManagerRetriever的get方法获取RequestManager,不同的context(Activity,Fragment,ApplicationContext)得到不同的RequestManager
至此,with方法分析完成,为我们完成加载图片前的平台侧准备工作,这里的平台指的是Glide。
load方法解析
前面讲解构造函数知道load(url)是RequestManager的方法,RequestManager是用来管理和启动request的。
A class for managing and starting requests for Glide.
RequestManager是with方法中getRetriever(context).get(context)获取的。getRetriever(context)得到RequestManagerRetriever,然后调用RequestManagerRetriever的get方法获取RequestManager。
现在去看下load方法,这里我们就比较熟悉了,我们知道glide非常贴心的为我们支持了很多类型,Bitmap,url,drawable, 资源id,文件等等。
//RequestManager.javapublic RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {return asDrawable().load(bitmap);}public RequestBuilder<Drawable> load(@Nullable String string) {return asDrawable().load(string);}public RequestBuilder<Drawable> load(@Nullable Uri uri) {return asDrawable().load(uri);}public RequestBuilder<Drawable> load(@Nullable File file) {return asDrawable().load(file);}public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {return asDrawable().load(resourceId);}public RequestBuilder<Drawable> load(@Nullable URL url) {return asDrawable().load(url);}public RequestBuilder<Drawable> load(@Nullable byte[] model) {return asDrawable().load(model);}public RequestBuilder<Drawable> load(@Nullable Object model) {return asDrawable().load(model);}
他们都调用了一个asDrawable()方法,返回一个RequestBuilder,是一个泛型类,可以处理泛型资源类型的设置选项和开始加载。既然是泛型类,除了这里的Drawable,还用到哪些类型呢?还有Bitmap,GifDrawable,File,这里主要分析核心流程,这里主要看Drawable,也是我们最常用的。下面去看下asDrawable的实现。
public RequestBuilder<Drawable> asDrawable() {return as(Drawable.class);}public <ResourceType> RequestBuilder<ResourceType> as(@NonNull Class<ResourceType> resourceClass) {//构造RequestBuilder,注意这几个参数,第一个参数是glide对象,第二个是RequestManager自身,//第三个是resourceClass,也即是传进来的Drawable.class对象,第四个是上下文return new RequestBuilder<>(glide, this, resourceClass, context);}
asDrawable()也是返回一个RequestBuilder,前面RequestManager的load方法中都是调用了asDrawable().load方法,也就是RequestBuilder的load方法,说明后面执行load方法的也是新建的这个RequestBuilder执行的。然后再来看下
//RequestBuilder.javapublic RequestBuilder<TranscodeType> load(@Nullable String string) {//把参数传过去return loadGeneric(string);}@NonNullprivate RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {if (isAutoCloneEnabled()) {return clone().loadGeneric(model);}//这里model是一个Object,也就是可以接受任意类型this.model = model;isModelSet = true;return selfOrThrowIfLocked();}
其实就是给this.mode赋值,然后设置isModelSet为true,然后返回自身,也就是刚刚新建的RequestBuilder,RequestBuilder是BaseRequestOptions的子类。
//BaseRequestOptions.javaprotected final T selfOrThrowIfLocked() {if (isLocked) {throw new IllegalStateException("You cannot modify locked T, consider clone()");}return self();}private T self() {return (T) this;}
总结:load方法看着比较简单,仅仅是构造了一个RequestBuilder,后面调用的into方法也在RequestBuilder中,所以可以认为这里仅仅是对请求参数的一个准备,适配了所有的类型Bitmap,url,drawable, 资源id,文件等等。
into方法分析
前面主要是拿到了RequestBuilder对象,执行into方法的是在RequestBuilder中
//RequestBuilder.java
@NonNullpublic ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {//检查是否在主线程,否则抛异常Util.assertMainThread();//检查要显示图片的view是否为空Preconditions.checkNotNull(view);//赋值BaseRequestOptions,RequestBuilder继承自BaseRequestOptionsBaseRequestOptions<?> requestOptions = this;//判断是否设置Transformation等变换if (!requestOptions.isTransformationSet()&& requestOptions.isTransformationAllowed()&& view.getScaleType() != null) {// Clone in this method so that if we use this RequestBuilder to load into a View and then// into a different target, we don't retain the transformation applied based on the previous// View's scale type.switch (view.getScaleType()) {case CENTER_CROP://这里用到了原型模式requestOptions = requestOptions.clone().optionalCenterCrop();break;case CENTER_INSIDE:requestOptions = requestOptions.clone().optionalCenterInside();break;case FIT_CENTER:case FIT_START:case FIT_END:requestOptions = requestOptions.clone().optionalFitCenter();break;case FIT_XY:requestOptions = requestOptions.clone().optionalCenterInside();break;case CENTER:case MATRIX:default:// Do nothing.}}return into(glideContext.buildImageViewTarget(view, transcodeClass),/* targetListener= */ null,requestOptions,Executors.mainThreadExecutor());}
看下传入的几个参数
- glideContext.buildImageViewTarget(view, transcodeClass) -> 构建一个Target对象
- null->targetListener传入的为空
- requestOptions->也就是自身
- Executor->这里传入的是主线程Executor
这里我们先看下Target的构造过程,后面会用到
//GlideContext.java
public <X> ViewTarget<ImageView, X> buildImageViewTarget(@NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {//将ImageView和transcodeClass调用imageViewTargetFactory的buildTargetreturn imageViewTargetFactory.buildTarget(imageView, transcodeClass);}
ImageViewTargetFactory的buildTarget方法是根据transcodeClass类型创建不同的Target,如BitmapImageViewTarget和DrawableImageViewTarget
//ImageViewTargetFactory.java
public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view, @NonNull Class<Z> clazz) {if (Bitmap.class.equals(clazz)) {return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);} else if (Drawable.class.isAssignableFrom(clazz)) {return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);} else {throw new IllegalArgumentException("Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");}}
//RequestBuilder.java
private <Y extends Target<TranscodeType>> Y into(@NonNull Y target,@Nullable RequestListener<TranscodeType> targetListener,BaseRequestOptions<?> options,Executor callbackExecutor) {//检查target是否为nullPreconditions.checkNotNull(target);//还记得前面load方法中有设置这个为trueif (!isModelSet) {throw new IllegalArgumentException("You must call #load() before calling #into()");}//构建requestRequest request = buildRequest(target, targetListener, options, callbackExecutor);Request previous = target.getRequest();//拿到上一次的request,如果和以前的一样if (request.isEquivalentTo(previous)&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {//如果request已经完成,重新开始以保证结果可以被传递//如果request已经失败,重新开始请求,给它第二次成功的机会//如果在运行,我们让他继续运行if (!Preconditions.checkNotNull(previous).isRunning()) {// Use the previous request rather than the new one to allow for optimizations like skipping// setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions// that are done in the individual Request.previous.begin();}return target;}//清空targetrequestManager.clear(target);//给target设置为当前的requesttarget.setRequest(request);//添加追踪,并开始执行requestManager.track(target, request);return target;}
后面分三个方向,这三个方法也是into方法主要做的几件事:
- 如何构造request
- 如何请求request
- 如何把请求结果显示到ImageView上
如何构造request
private Request buildRequest(Target<TranscodeType> target,@Nullable RequestListener<TranscodeType> targetListener,BaseRequestOptions<?> requestOptions,Executor callbackExecutor) {return buildRequestRecursive(/* requestLock= */ new Object(),//请求锁target,//目标targetListener,//目标监听器,前面看到这里传来的是null/* parentCoordinator= */ null,transitionOptions,//转换选项requestOptions.getPriority(),//请求选项-优先级requestOptions.getOverrideWidth(),//请求选项-复写宽度requestOptions.getOverrideHeight(),//请求选项-复写高度requestOptions,//请求选项callbackExecutor //回调执行器);}
private Request buildRequestRecursive(...) {// Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.ErrorRequestCoordinator errorRequestCoordinator = null;//前面Demo没有设置error,这里为nullif (errorBuilder != null) {errorRequestCoordinator = new ErrorRequestCoordinator(requestLock, parentCoordinator);parentCoordinator = errorRequestCoordinator;}Request mainRequest =buildThumbnailRequestRecursive(requestLock,target,targetListener,parentCoordinator,transitionOptions,priority,overrideWidth,overrideHeight,requestOptions,callbackExecutor);if (errorRequestCoordinator == null) {return mainRequest;}...return errorRequestCoordinator;}
private Request buildThumbnailRequestRecursive(Object requestLock,Target<TranscodeType> target,RequestListener<TranscodeType> targetListener,@Nullable RequestCoordinator parentCoordinator,TransitionOptions<?, ? super TranscodeType> transitionOptions,Priority priority,int overrideWidth,int overrideHeight,BaseRequestOptions<?> requestOptions,Executor callbackExecutor) {if (thumbnailBuilder != null) {//前面Demo中没有设置thumbnail,不会走到这里先忽略...} else if (thumbSizeMultiplier != null) {//前面Demo中没有设置thumbnail,不会走到这里先忽略...} else {// Base case: no thumbnail.return obtainRequest(requestLock,target,targetListener,requestOptions,parentCoordinator,transitionOptions,priority,overrideWidth,overrideHeight,callbackExecutor);}}
最后走到obtainRequest,通过SingleRequest.obtain,最终在SingleRequest.java中直接新建了一个SingleRequest
private Request obtainRequest(Object requestLock,Target<TranscodeType> target,RequestListener<TranscodeType> targetListener,BaseRequestOptions<?> requestOptions,RequestCoordinator requestCoordinator,TransitionOptions<?, ? super TranscodeType> transitionOptions,Priority priority,int overrideWidth,int overrideHeight,Executor callbackExecutor) {return SingleRequest.obtain(context,glideContext,requestLock,model,transcodeClass,requestOptions,overrideWidth,overrideHeight,priority,target,targetListener,requestListeners,requestCoordinator,glideContext.getEngine(),transitionOptions.getTransitionFactory(),callbackExecutor);}
如何请求request
通过看Request接口说明,知道begin()是开始一个请求,在前面requestManager.track(target, request);会最终调用到begin()方法。
//RequestManager.javasynchronized void track(@NonNull Target<?> target, @NonNull Request request) {targetTracker.track(target);requestTracker.runRequest(request);}//RequestTracker.javapublic void runRequest(@NonNull Request request) {requests.add(request);if (!isPaused) {//启动request.begin();} else {request.clear();if (Log.isLoggable(TAG, Log.VERBOSE)) {Log.v(TAG, "Paused, delaying request");}pendingRequests.add(request);}}
public interface Request {//启动一个异步请求void begin();//取消,清空请求void clear();//暂停请求void pause();//是否在运行中boolean isRunning();//请求是否完成boolean isComplete();//请求是否被clearboolean isCleared();/*** Returns true if a resource is set, even if the request is not yet complete or the primary* request has failed.*/boolean isAnyResourceSet();//和另一个请求是否相等boolean isEquivalentTo(Request other);
}
下面我们去看SingleRequest的begin方法的实现
//SingleRequest.java
public void begin() {synchronized (requestLock) {assertNotCallingCallbacks();stateVerifier.throwIfRecycled();startTime = LogTime.getLogTime();if (model == null) {if (Util.isValidDimensions(overrideWidth, overrideHeight)) {width = overrideWidth;height = overrideHeight;}// Only log at more verbose log levels if the user has set a fallback drawable, because// fallback Drawables indicate the user expects null models occasionally.int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;onLoadFailed(new GlideException("Received null model"), logLevel);return;}if (status == Status.RUNNING) {throw new IllegalArgumentException("Cannot restart a running request");}// If we're restarted after we're complete (usually via something like a notifyDataSetChanged// that starts an identical request into the same Target or View), we can simply use the// resource and size we retrieved the last time around and skip obtaining a new size, starting// a new load etc. This does mean that users who want to restart a load because they expect// that the view size has changed will need to explicitly clear the View or Target before// starting the new load.if (status == Status.COMPLETE) {onResourceReady(resource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);return;}// Restarts for requests that are neither complete nor running can be treated as new requests// and can run again from the beginning.experimentalNotifyRequestStarted(model);cookie = GlideTrace.beginSectionAsync(TAG);status = Status.WAITING_FOR_SIZE;if (Util.isValidDimensions(overrideWidth, overrideHeight)) {//如果overrideWidth,overrideHeight都是有效的,直接调用onSizeReadyonSizeReady(overrideWidth, overrideHeight);} else {//否则调用target.getSize,并把自身传入,因为SingleRequest实现了SizeReadyCallback,获取成功最终还是回调到onSizeReady方法target.getSize(this);}if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)&& canNotifyStatusChanged()) {target.onLoadStarted(getPlaceholderDrawable());}if (IS_VERBOSE_LOGGABLE) {logV("finished run method in " + LogTime.getElapsedMillis(startTime));}}}
最终都是调用到onSizeReady方法,onSizeReady方法中调用的是engine的load方法,engine是在Glide的建造者中构造的
//SingleRequest.java
public void onSizeReady(int width, int height) {stateVerifier.throwIfRecycled();synchronized (requestLock) {if (IS_VERBOSE_LOGGABLE) {logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));}if (status != Status.WAITING_FOR_SIZE) {//如果还在等待size结果。直接返回return;}//将status设置为Status.RUNNINGstatus = Status.RUNNING;float sizeMultiplier = requestOptions.getSizeMultiplier();this.width = maybeApplySizeMultiplier(width, sizeMultiplier);this.height = maybeApplySizeMultiplier(height, sizeMultiplier);if (IS_VERBOSE_LOGGABLE) {logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));}//调用引擎的load方法加载图片loadStatus =engine.load(glideContext,model,requestOptions.getSignature(),this.width,this.height,requestOptions.getResourceClass(),transcodeClass,priority,requestOptions.getDiskCacheStrategy(),requestOptions.getTransformations(),requestOptions.isTransformationRequired(),requestOptions.isScaleOnlyOrNoTransform(),requestOptions.getOptions(),requestOptions.isMemoryCacheable(),requestOptions.getUseUnlimitedSourceGeneratorsPool(),requestOptions.getUseAnimationPool(),requestOptions.getOnlyRetrieveFromCache(),this,//传入回调callbackExecutor);// This is a hack that's only useful for testing right now where loads complete synchronously// even though under any executor running on any thread but the main thread, the load would// have completed asynchronously.if (status != Status.RUNNING) {loadStatus = null;}if (IS_VERBOSE_LOGGABLE) {logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));}}}
需要注意的是load方法传入了一个ResourceCallback cb参数,这个接口就是加载结果的回调。
public interface ResourceCallback {//加载成功void onResourceReady(Resource<?> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey);//加载失败void onLoadFailed(GlideException e);Object getLock();
}
//Engine.java
public <R> LoadStatus load(...) {long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;EngineKey key =keyFactory.buildKey(model,signature,width,height,transformations,resourceClass,transcodeClass,options);EngineResource<?> memoryResource;//加锁,同一时间内只能添加一个加载工作synchronized (this) {//先重缓存中加载memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);if (memoryResource == null) {//缓存没有return waitForExistingOrStartNewJob(glideContext,model,signature,width,height,resourceClass,transcodeClass,priority,diskCacheStrategy,transformations,isTransformationRequired,isScaleOnlyOrNoTransform,options,isMemoryCacheable,useUnlimitedSourceExecutorPool,useAnimationPool,onlyRetrieveFromCache,cb,callbackExecutor,key,startTime);}}// Avoid calling back while holding the engine lock, doing so makes it easier for callers to// deadlock.cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);return null;}
分析缓存加载流程
//Engine.java
private EngineResource<?> loadFromMemory(EngineKey key, boolean isMemoryCacheable, long startTime) {if (!isMemoryCacheable) {return null;}//先从活跃缓存中加载EngineResource<?> active = loadFromActiveResources(key);if (active != null) {if (VERBOSE_IS_LOGGABLE) {logWithTimeAndKey("Loaded resource from active resources", startTime, key);}return active;}//活跃缓存没有找到,继续去非活跃缓存中加载EngineResource<?> cached = loadFromCache(key);if (cached != null) {if (VERBOSE_IS_LOGGABLE) {logWithTimeAndKey("Loaded resource from cache", startTime, key);}return cached;}//都没查到,返回nullreturn null;}
活跃缓存是直接在Map中
private EngineResource<?> loadFromActiveResources(Key key) {//ActiveResources的实例,里面存放的是Map<Key, ResourceWeakReference>EngineResource<?> active = activeResources.get(key);if (active != null) {active.acquire();}return active;}
从缓存中加载,缓存对象是Engine构造的时候传入的,最开始在Glide构建时候新建的LruResourceCache,是Glide自己实现的LRU
private EngineResource<?> loadFromCache(Key key) {EngineResource<?> cached = getEngineResourceFromCache(key);if (cached != null) {cached.acquire();activeResources.activate(key, cached);}return cached;}private EngineResource<?> getEngineResourceFromCache(Key key) {Resource<?> cached = cache.remove(key);final EngineResource<?> result;if (cached == null) {result = null;} else if (cached instanceof EngineResource) {// Save an object allocation if we've cached an EngineResource (the typical case).result = (EngineResource<?>) cached;} else {result =new EngineResource<>(cached,/* isMemoryCacheable= */ true,/* isRecyclable= */ true,key,/* listener= */ this);}return result;}
缓存没有查到,会调用waitForExistingOrStartNewJob方法,等待已经存在的任务或者开启新的任务。
//Engine.java
private <R> LoadStatus waitForExistingOrStartNewJob(...) {//先从jobs里面查询是否有加入过EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);if (current != null) {current.addCallback(cb, callbackExecutor);if (VERBOSE_IS_LOGGABLE) {logWithTimeAndKey("Added to existing load", startTime, key);}//查询到,直接返回LoadStatus,加载的状态return new LoadStatus(cb, current);}//没查到,通过engineJobFactory工厂构建一个新的EngineJobEngineJob<R> engineJob =engineJobFactory.build(key,isMemoryCacheable,useUnlimitedSourceExecutorPool,useAnimationPool,onlyRetrieveFromCache);//在通过解码job工厂构建一个新的解码jobDecodeJob<R> decodeJob =decodeJobFactory.build(glideContext,model,key,signature,width,height,resourceClass,transcodeClass,priority,diskCacheStrategy,transformations,isTransformationRequired,isScaleOnlyOrNoTransform,onlyRetrieveFromCache,options,engineJob);//添加到 jobs里面jobs.put(key, engineJob);//添加回调engineJob.addCallback(cb, callbackExecutor);//启动加载工作engineJob.start(decodeJob);if (VERBOSE_IS_LOGGABLE) {logWithTimeAndKey("Started new load", startTime, key);}//返回加载状态return new LoadStatus(cb, engineJob);}
下面分析几个点
- Jobs
- LoadStatus
- EngineJob
- DecodeJob
Jobs
Jobs比较简单,可以理解为就是个工作存储器。有两个Map,
- jobs 存储普通服务的Map
- onlyCacheJobs 存储只从缓存取的job的Map
final class Jobs {private final Map<Key, EngineJob<?>> jobs = new HashMap<>();private final Map<Key, EngineJob<?>> onlyCacheJobs = new HashMap<>();@VisibleForTestingMap<Key, EngineJob<?>> getAll() {return Collections.unmodifiableMap(jobs);}EngineJob<?> get(Key key, boolean onlyRetrieveFromCache) {return getJobMap(onlyRetrieveFromCache).get(key);}void put(Key key, EngineJob<?> job) {getJobMap(job.onlyRetrieveFromCache()).put(key, job);}void removeIfCurrent(Key key, EngineJob<?> expected) {Map<Key, EngineJob<?>> jobMap = getJobMap(expected.onlyRetrieveFromCache());if (expected.equals(jobMap.get(key))) {jobMap.remove(key);}}private Map<Key, EngineJob<?>> getJobMap(boolean onlyRetrieveFromCache) {return onlyRetrieveFromCache ? onlyCacheJobs : jobs;}
}
LoadStatus
LoadStatus就更简单了,仅仅是包装了engineJob和cb()回调。并提供了一个cancel方法。所以核心就是可以取消请求。
public class LoadStatus {private final EngineJob<?> engineJob;private final ResourceCallback cb;LoadStatus(ResourceCallback cb, EngineJob<?> engineJob) {this.cb = cb;this.engineJob = engineJob;}public void cancel() {synchronized (Engine.this) {engineJob.removeCallback(cb);}}}
EngineJob
EngineJob虽然叫job但是并没有实现Runnable接口,在start启动了decodeJob
//EngineJob.java
public synchronized void start(DecodeJob<R> decodeJob) {this.decodeJob = decodeJob;GlideExecutor executor =decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();executor.execute(decodeJob);}
DecodeJob
EngineJob其实仅仅是对DecodeJob的包裹,真正实现请求的地方在DecodeJob。DecodeJob实现了Runnable接口,由线程执行器调度启动。
//DecodeJob.java
public void run() {...DataFetcher<?> localFetcher = currentFetcher;try {if (isCancelled) {notifyFailed();return;}runWrapped();...} finally {// Keeping track of the fetcher here and calling cleanup is excessively paranoid, we call// close in all cases anyway.if (localFetcher != null) {localFetcher.cleanup();}GlideTrace.endSection();}}
下面去看runWrapped方法,runWrapped,又调用了getNextStage方法,这里用到了两个设计模式:责任链模式和策略模式。
runReason,执行任务的原因,三种枚举值:
- INITIALIZE:第一次调度任务
- WITCH_TO_SOURCE_SERVICE:本地缓存策略失败,尝试重新获取数据,两种情况;当stage为Stage.SOURCE,或者获取数据失败并且执行和回调发生在了不同的线程
- DECODE_DATA:获取数据成功,但执行和回调不在同一线程,希望回到自己的线程去处理数据
getNextStage:获取下一步的状态
- INITIALIZE:初始化状态
- RESOURCE_CACHE:从缓存资源加载
- DATA_CACHE:从缓存数据加载
- SOURCE:从源加载获取
- ENCODE:加载完成后编码成需要的资源
- FINISHED:完成
getNextGenerator:获取下一个Generator
- ResourceCacheGenerator :尝试从修改过的资源缓存中获取,如果缓存未命中,尝试从DATA_CACHE中获取
- DataCacheGenerator 尝试从未修改过的本地缓存中获取数据,如果缓存未命中则尝试从SourceGenerator中获取
- SourceGenerator 从原始的资源中获取,可能是服务器,也可能是本地的一些原始资源
//DecodeJob.javaprivate void runWrapped() {switch (runReason) {//首次runReason默认是INITIALIZEcase INITIALIZE://返回Stage.RESOURCE_CACHEstage = getNextStage(Stage.INITIALIZE);//currentGenerator = getNextGenerator();runGenerators();break;case SWITCH_TO_SOURCE_SERVICE:runGenerators();break;case DECODE_DATA:decodeFromRetrievedData();break;default:throw new IllegalStateException("Unrecognized run reason: " + runReason);}}private DataFetcherGenerator getNextGenerator() {switch (stage) {case RESOURCE_CACHE://首次stage为RESOURCE_CACHE返回ResourceCacheGenerator实例return new ResourceCacheGenerator(decodeHelper, this);case DATA_CACHE:return new DataCacheGenerator(decodeHelper, this);case SOURCE:return new SourceGenerator(decodeHelper, this);case FINISHED:return null;default:throw new IllegalStateException("Unrecognized stage: " + stage);}}private Stage getNextStage(Stage current) {switch (current) {case INITIALIZE://策略模式,根据不同的策略返回不同的结果,默认是ALL那个实例return diskCacheStrategy.decodeCachedResource()? Stage.RESOURCE_CACHE: getNextStage(Stage.RESOURCE_CACHE);case RESOURCE_CACHE:return diskCacheStrategy.decodeCachedData()? Stage.DATA_CACHE: getNextStage(Stage.DATA_CACHE);case DATA_CACHE:// Skip loading from source if the user opted to only retrieve the resource from cache.return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;case SOURCE:case FINISHED:return Stage.FINISHED;default:throw new IllegalArgumentException("Unrecognized stage: " + current);}}private void runGenerators() {currentThread = Thread.currentThread();startFetchTime = LogTime.getLogTime();boolean isStarted = false;//首次currentGenerator为ResourceCacheGeneratorwhile (!isCancelled&& currentGenerator != null&& !(isStarted = currentGenerator.startNext())) {//只要返回的isStarted不是true,就不断的去下一个阶段找stage = getNextStage(stage);currentGenerator = getNextGenerator();if (stage == Stage.SOURCE) {//当stage为Stage.SOURCE的时候表示需要去请求数据,这个时候调用reschedulereschedule(RunReason.SWITCH_TO_SOURCE_SERVICE);return;}}// We've run out of stages and generators, give up.if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {notifyFailed();}// Otherwise a generator started a new load and we expect to be called back in// onDataFetcherReady.}
以上请求对于我们首次加载的网络图片,最终会走到SourceGenerator的startNext()方法,startNext()又调用到startNextLoad()方法
//SourceGenerator.java
public boolean startNext() {...sourceCacheGenerator = null;loadData = null;boolean started = false;while (!started && hasNextModelLoader()) {loadData = helper.getLoadData().get(loadDataListIndex++);if (loadData != null&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {started = true;startNextLoad(loadData);}}return started;}private void startNextLoad(final LoadData<?> toStart) {loadData.fetcher.loadData(helper.getPriority(),new DataCallback<Object>() {@Overridepublic void onDataReady(@Nullable Object data) {if (isCurrentRequest(toStart)) {onDataReadyInternal(toStart, data);}}@Overridepublic void onLoadFailed(@NonNull Exception e) {if (isCurrentRequest(toStart)) {onLoadFailedInternal(toStart, e);}}});}
这里关于数据加载过程,这里暂时不再深入,后面有时间再深入。最终看回调是到了onDataReadyInternal,
//SourceGenerator.java
void onDataReadyInternal(LoadData<?> loadData, Object data) {DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();//如果数据不为空,并且磁盘缓存策略认为这个资源是可以被缓存的,执行写入磁盘操作。if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {dataToCache = data;// We might be being called back on someone else's thread. Before doing anything, we should// reschedule to get back onto Glide's thread. Then once we're back on Glide's thread, we'll// get called again and we can write the retrieved data to cache.cb.reschedule();} else {cb.onDataFetcherReady(loadData.sourceKey,data,loadData.fetcher,loadData.fetcher.getDataSource(),originalKey);}}
上面如果磁盘缓存策略认为这个资源是可以被缓存的,执行写入磁盘缓存的操作。具体怎么执行的感兴趣的朋友可以看看。有点绕,不过就像方法名起的那样再次执行,多走了一次圈罢了。又回到DecodeJob的onDataFetcherReady将数据解码出来
public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {this.currentSourceKey = sourceKey;this.currentData = data;this.currentFetcher = fetcher;this.currentDataSource = dataSource;this.currentAttemptingKey = attemptedKey;this.isLoadingFromAlternateCacheKey = sourceKey != decodeHelper.getCacheKeys().get(0);if (Thread.currentThread() != currentThread) {reschedule(RunReason.DECODE_DATA);} else {GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");try {decodeFromRetrievedData();} finally {GlideTrace.endSection();}}}private void decodeFromRetrievedData() {if (Log.isLoggable(TAG, Log.VERBOSE)) {logWithTimeAndKey("Retrieved data",startFetchTime,"data: "+ currentData+ ", cache key: "+ currentSourceKey+ ", fetcher: "+ currentFetcher);}Resource<R> resource = null;try {//解码过程这里暂不分析resource = decodeFromData(currentFetcher, currentData, currentDataSource);} catch (GlideException e) {e.setLoggingDetails(currentAttemptingKey, currentDataSource);throwables.add(e);}if (resource != null) {//解码资源不为空,通知notifyEncodeAndRelease(resource, currentDataSource, isLoadingFromAlternateCacheKey);} else {runGenerators();}}
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {GlideTrace.beginSection("DecodeJob.notifyEncodeAndRelease");try {if (resource instanceof Initializable) {((Initializable) resource).initialize();}Resource<R> result = resource;LockedResource<R> lockedResource = null;if (deferredEncodeManager.hasResourceToEncode()) {lockedResource = LockedResource.obtain(resource);result = lockedResource;}notifyComplete(result, dataSource, isLoadedFromAlternateCacheKey);stage = Stage.ENCODE;try {if (deferredEncodeManager.hasResourceToEncode()) {deferredEncodeManager.encode(diskCacheProvider, options);}} finally {if (lockedResource != null) {lockedResource.unlock();}}// Call onEncodeComplete outside the finally block so that it's not called if the encode// process// throws.onEncodeComplete();} finally {GlideTrace.endSection();}}//通知完成
private void notifyComplete(Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {setNotifiedOrThrow();//最终调用callback的onResourceReadycallback.onResourceReady(resource, dataSource, isLoadedFromAlternateCacheKey);}
这里最终又调用回EngineJob的onResourceReady方法,最终调用到Engine.load方法执行的时候传入的ResourceCallback的onResourceReady。也就是SingleRequest的实现的onResourceReady方法
//EngineJob.java
private class CallResourceReady implements Runnable {private final ResourceCallback cb;CallResourceReady(ResourceCallback cb) {this.cb = cb;}@Overridepublic void run() {// Make sure we always acquire the request lock, then the EngineJob lock to avoid deadlock// (b/136032534).synchronized (cb.getLock()) {synchronized (EngineJob.this) {if (cbs.contains(cb)) {// Acquire for this particular callback.engineResource.acquire();callCallbackOnResourceReady(cb);removeCallback(cb);}decrementPendingCallbacks();}}}}
如何把请求结果显示到ImageView上
前面分析到,请求的结果最终回调到SingleRequest的实现的onResourceReady方法中
public void onResourceReady(Resource<?> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {stateVerifier.throwIfRecycled();Resource<?> toRelease = null;try {synchronized (requestLock) {loadStatus = null;if (resource == null) {//resource为空,抛异常GlideException exception =new GlideException(...);onLoadFailed(exception);return;}Object received = resource.get();if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {toRelease = resource;this.resource = null;//抛异常GlideException exception =new GlideException(...);onLoadFailed(exception);return;}if (!canSetResource()) {toRelease = resource;this.resource = null;// We can't put the status to complete before asking canSetResource().status = Status.COMPLETE;GlideTrace.endSectionAsync(TAG, cookie);return;}//调用复写的onResourceReady方法onResourceReady((Resource<R>) resource, (R) received, dataSource, isLoadedFromAlternateCacheKey);}} finally {if (toRelease != null) {engine.release(toRelease);}}}
private void onResourceReady(Resource<R> resource, R result, DataSource dataSource, boolean isAlternateCacheKey) {// We must call isFirstReadyResource before setting status.boolean isFirstResource = isFirstReadyResource();status = Status.COMPLETE;this.resource = resource;...notifyRequestCoordinatorLoadSucceeded();isCallingCallbacks = true;try {boolean anyListenerHandledUpdatingTarget = false;if (requestListeners != null) {for (RequestListener<R> listener : requestListeners) {anyListenerHandledUpdatingTarget |=listener.onResourceReady(result, model, target, dataSource, isFirstResource);if (listener instanceof ExperimentalRequestListener) {ExperimentalRequestListener<R> experimentalRequestListener =(ExperimentalRequestListener<R>) listener;anyListenerHandledUpdatingTarget |=experimentalRequestListener.onResourceReady(result, model, target, dataSource, isFirstResource, isAlternateCacheKey);}}}anyListenerHandledUpdatingTarget |=targetListener != null&& targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);if (!anyListenerHandledUpdatingTarget) {Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource);//调用target的onResourceReady方法target.onResourceReady(result, animation);}} finally {isCallingCallbacks = false;}GlideTrace.endSectionAsync(TAG, cookie);}
//ImageViewTarget.javapublic void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {if (transition == null || !transition.transition(resource, this)) {setResourceInternal(resource);} else {maybeUpdateAnimatable(resource);}}private void setResourceInternal(@Nullable Z resource) {// Order matters here. Set the resource first to make sure that the Drawable has a valid and// non-null Callback before starting it.setResource(resource);maybeUpdateAnimatable(resource);}protected abstract void setResource(@Nullable Z resource);
还记得上面target的构造过程吗,ImageViewTarget有几个实现类,其中就是BitmapImageViewTarget和DrawableImageViewTarget,这里构建的是BitmapImageViewTarget, 我们看下setResource的实现
protected void setResource(Bitmap resource) {//最终调用View的setImageBitmap方法view.setImageBitmap(resource);}
如何感知生命周期
还记得前面RequestManager构造的时候有三种情况,context,FragmentActivity,Fragment。对于FragmentActivity,Fragment,构造的时候会分别传入activity.getLifecycle(),fragment.getLifecycle()。
RequestManager getOrCreate(Context context,Glide glide,final Lifecycle lifecycle,FragmentManager childFragmentManager,boolean isParentVisible) {Util.assertMainThread();RequestManager result = getOnly(lifecycle);if (result == null) {//先生成一个LifecycleLifecycle把上面传进来的Lifecycle作为参数LifecycleLifecycle glideLifecycle = new LifecycleLifecycle(lifecycle);result =factory.build(glide,glideLifecycle,new SupportRequestManagerTreeNode(childFragmentManager),context);lifecycleToRequestManager.put(lifecycle, result);glideLifecycle.addListener(new LifecycleListener() {@Overridepublic void onStart() {}@Overridepublic void onStop() {}@Overridepublic void onDestroy() {lifecycleToRequestManager.remove(lifecycle);}});// 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/154405040if (isParentVisible) {result.onStart();}}return result;}
LifecycleLifecycle比较简单,就是新建了一个Set lifecycleListeners,然后addListener的时候把传进来的LifecycleListener存储到lifecycleListeners里面。LifecycleLifecycle构造方法中会把本身绑定到Android系统的androidx.lifecycle.Lifecycle监听
final class LifecycleLifecycle implements Lifecycle, LifecycleObserver {@NonNullprivate final Set<LifecycleListener> lifecycleListeners = new HashSet<LifecycleListener>();@NonNull private final androidx.lifecycle.Lifecycle lifecycle;LifecycleLifecycle(androidx.lifecycle.Lifecycle lifecycle) {this.lifecycle = lifecycle;lifecycle.addObserver(this);}@OnLifecycleEvent(Event.ON_START)public void onStart(@NonNull LifecycleOwner owner) {//通知所有的LifecycleListener,Util.getSnapshot是为了线程安全,每次都copy出一份for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {lifecycleListener.onStart();}}@OnLifecycleEvent(Event.ON_STOP)public void onStop(@NonNull LifecycleOwner owner) {for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {lifecycleListener.onStop();}}@OnLifecycleEvent(Event.ON_DESTROY)public void onDestroy(@NonNull LifecycleOwner owner) {for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {lifecycleListener.onDestroy();}owner.getLifecycle().removeObserver(this);}@Overridepublic void addListener(@NonNull LifecycleListener listener) {lifecycleListeners.add(listener);if (lifecycle.getCurrentState() == State.DESTROYED) {listener.onDestroy();} else if (lifecycle.getCurrentState().isAtLeast(State.STARTED)) {listener.onStart();} else {listener.onStop();}}@Overridepublic void removeListener(@NonNull LifecycleListener listener) {lifecycleListeners.remove(listener);}
}
RequestManager(...) {...if (Util.isOnBackgroundThread()) {Util.postOnUiThread(addSelfToLifecycle);} else {//这里将RequestManager实例添加到lifecycle的监听器集合中lifecycle.addListener(this);}...}
如何监控网络变化
前面分析监控生命周期的时候,注意到一个connectivityMonitor也被添加到生命周期监控集合中
RequestManager(...) {...connectivityMonitor =factory.build(context.getApplicationContext(),new RequestManagerConnectivityListener(requestTracker));...//这里将connectivityMonitor添加到lifecycle的监听器集合中lifecycle.addListener(connectivityMonitor);...}
ConnectivityMonitorFactory的实现只有一个DefaultConnectivityMonitorFactory,我们去看它的build方法
public class DefaultConnectivityMonitorFactory implements ConnectivityMonitorFactory {private static final String TAG = "ConnectivityMonitor";private static final String NETWORK_PERMISSION = "android.permission.ACCESS_NETWORK_STATE";@NonNull@Overridepublic ConnectivityMonitor build(@NonNull Context context, @NonNull ConnectivityMonitor.ConnectivityListener listener) {int permissionResult = ContextCompat.checkSelfPermission(context, NETWORK_PERMISSION);boolean hasPermission = permissionResult == PackageManager.PERMISSION_GRANTED;...return hasPermission? new DefaultConnectivityMonitor(context, listener): new NullConnectivityMonitor();}
}
这里主要新建了一个DefaultConnectivityMonitor,因为NullConnectivityMonitor是没有权限的时候才去新建的,方法都是空实现。
final class DefaultConnectivityMonitor implements ConnectivityMonitor {private final Context context;@SuppressWarnings("WeakerAccess")@Syntheticfinal ConnectivityListener listener;DefaultConnectivityMonitor(@NonNull Context context, @NonNull ConnectivityListener listener) {this.context = context.getApplicationContext();this.listener = listener;}private void register() {SingletonConnectivityReceiver.get(context).register(listener);}private void unregister() {SingletonConnectivityReceiver.get(context).unregister(listener);}@Overridepublic void onStart() {register();}@Overridepublic void onStop() {unregister();}@Overridepublic void onDestroy() {// Do nothing.}
}
核心就是在onStart()注册一个监听,在onStop()取消注册监听。SingletonConnectivityReceiver是个单例模式实现的网络状态监听器。
final class SingletonConnectivityReceiver {private static volatile SingletonConnectivityReceiver instance;@GuardedBy("this")@Syntheticfinal Set<ConnectivityListener> listeners = new HashSet<ConnectivityListener>();//单例模式实现SingletonConnectivityReceiverstatic SingletonConnectivityReceiver get(@NonNull Context context) {if (instance == null) {synchronized (SingletonConnectivityReceiver.class) {if (instance == null) {instance = new SingletonConnectivityReceiver(context.getApplicationContext());}}}return instance;}private SingletonConnectivityReceiver(final @NonNull Context context) {GlideSupplier<ConnectivityManager> connectivityManager =GlideSuppliers.memorize(new GlideSupplier<ConnectivityManager>() {@Overridepublic ConnectivityManager get() {return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);}});ConnectivityListener connectivityListener =new ConnectivityListener() {@Overridepublic void onConnectivityChanged(boolean isConnected) {//网络状态发生变化的时候通知所有的listenersUtil.assertMainThread();List<ConnectivityListener> toNotify;synchronized (SingletonConnectivityReceiver.this) {toNotify = new ArrayList<>(listeners);}for (ConnectivityListener listener : toNotify) {listener.onConnectivityChanged(isConnected);}}};frameworkConnectivityMonitor =Build.VERSION.SDK_INT >= Build.VERSION_CODES.N? new FrameworkConnectivityMonitorPostApi24(connectivityManager, connectivityListener): new FrameworkConnectivityMonitorPreApi24(context, connectivityManager, connectivityListener);}synchronized void register(ConnectivityListener listener) {listeners.add(listener);maybeRegisterReceiver();}/*** To avoid holding a lock while notifying listeners, the unregistered listener may still be* notified about a connectivity change after this method completes if this method is called on a* thread other than the main thread and if a connectivity broadcast is racing with this method.* Callers must handle this case.*/synchronized void unregister(ConnectivityListener listener) {listeners.remove(listener);maybeUnregisterReceiver();}...
}
用到哪些设计模式
- 单例模式
- 建造者模式
- 外观模式
- 享元模式
- 原型模式
- 观察者模式
- 简单工厂
- 工厂方法
- 责任链模式
- 策略模式
参考链接
https://juejin.cn/post/7044079102839488543?searchId=202410100927002AB04F7243D94B6586AA
https://blog.csdn.net/Love667767/article/details/106576888/
https://www.cnblogs.com/android-blogs/p/5735655.htmlun