//Glide.javapublicstaticRequestManagerwith(@NonNullActivityactivity){//先获取RequestManagerRetriever对象//调用RequestManagerRetriever的get方法获取RequestManagerreturngetRetriever(activity).get(activity);}privatestaticRequestManagerRetrievergetRetriever(@NullableContextcontext){// 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).");returnGlide.get(context).getRequestManagerRetriever();}
@GuardedBy("Glide.class")privatestaticvoidcheckAndInitializeGlide(@NonNullContextcontext,@NullableGeneratedAppGlideModulegeneratedAppGlideModule){// 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){thrownewIllegalStateException("You cannot call Glide.get() in registerComponents(),"+" use the provided Glide instance instead");}isInitializing=true;initializeGlide(context,generatedAppGlideModule);isInitializing=false;}
@GuardedBy("Glide.class")@SuppressWarnings("deprecation")privatestaticvoidinitializeGlide(@NonNullContextcontext,@NonNullGlideBuilderbuilder,@NullableGeneratedAppGlideModuleannotationGeneratedModule){ContextapplicationContext=context.getApplicationContext();List<com.bumptech.glide.module.GlideModule>manifestModules=Collections.emptyList();if(annotationGeneratedModule==null||annotationGeneratedModule.isManifestParsingEnabled()){//解析ManifestParser 老的Glide版本需要在清单文件中注册GlideModulemanifestModules=newManifestParser(applicationContext).parse();}if(annotationGeneratedModule!=null&&!annotationGeneratedModule.getExcludedModuleClasses().isEmpty()){Set<Class<?>>excludedModuleClasses=annotationGeneratedModule.getExcludedModuleClasses();Iterator<com.bumptech.glide.module.GlideModule>iterator=manifestModules.iterator();while(iterator.hasNext()){com.bumptech.glide.module.GlideModulecurrent=iterator.next();if(!excludedModuleClasses.contains(current.getClass())){continue;}if(Log.isLoggable(TAG,Log.DEBUG)){Log.d(TAG,"AppGlideModule excludes manifest GlideModule: "+current);}iterator.remove();}}if(Log.isLoggable(TAG,Log.DEBUG)){for(com.bumptech.glide.module.GlideModuleglideModule:manifestModules){Log.d(TAG,"Discovered GlideModule from manifest: "+glideModule.getClass());}}//获取RequestManagerFactory即GeneratedRequestManagerFactoryRequestManagerRetriever.RequestManagerFactoryfactory=annotationGeneratedModule!=null?annotationGeneratedModule.getRequestManagerFactory():null;//为GlideBuilder设置RequestManagerFactorybuilder.setRequestManagerFactory(factory);for(com.bumptech.glide.module.GlideModulemodule:manifestModules){module.applyOptions(applicationContext,builder);}if(annotationGeneratedModule!=null){annotationGeneratedModule.applyOptions(applicationContext,builder);}//调用build方法创建Glide对象Glideglide=builder.build(applicationContext);for(com.bumptech.glide.module.GlideModulemodule:manifestModules){try{module.registerComponents(applicationContext,glide,glide.registry);}catch(AbstractMethodErrore){thrownewIllegalStateException("Attempting to register a Glide v3 module. If you see this, you or one of your"+" dependencies may be including Glide v3 even though you're using Glide v4."+" You'll need to find and remove (or update) the offending dependency."+" The v3 module name is: "+module.getClass().getName(),e);}}if(annotationGeneratedModule!=null){annotationGeneratedModule.registerComponents(applicationContext,glide,glide.registry);}applicationContext.registerComponentCallbacks(glide);Glide.glide=glide;}
publicstaticGlideExecutor.BuildernewAnimationBuilder(){intbestThreadCount=calculateBestThreadCount();// We don't want to add a ton of threads running animations in parallel with our source and// disk cache executors. Doing so adds unnecessary CPU load and can also dramatically increase// our maximum memory usage. Typically one thread is sufficient here, but for higher end devices// with more cores, two threads can provide better performance if lots of GIFs are showing at// once.//我们不希望增加大量线程来并行运行动画,我们的源代码和磁盘缓存执行器。//这样做增加了不必要的CPU负载,也会大大增加了我们的最大内存使用量。//通常情况下,一个线程就足够了,但对于更高端的设备来说。//如果有更多的核心,两个线程可以提供更好的性能,如果大量的GIF显示一次。intmaximumPoolSize=bestThreadCount>=4?2:1;returnnewGlideExecutor.Builder(/*preventNetworkOperations=*/true).setThreadCount(maximumPoolSize).setName(DEFAULT_ANIMATION_EXECUTOR_NAME);}/** Shortcut for calling {@link Builder#build()} on {@link #newAnimationBuilder()}. */publicstaticGlideExecutornewAnimationExecutor(){returnnewAnimationBuilder().build();}
publicstaticfinalclassBuilder{@VisibleForTestingstaticfinalintMEMORY_CACHE_TARGET_SCREENS=2;/** * On Android O+, we use {@link android.graphics.Bitmap.Config#HARDWARE} for all reasonably * sized images unless we're creating thumbnails for the first time. As a result, the Bitmap * pool is much less important on O than it was on previous versions. */staticfinalintBITMAP_POOL_TARGET_SCREENS=Build.VERSION.SDK_INT<Build.VERSION_CODES.O?4:1;staticfinalfloatMAX_SIZE_MULTIPLIER=0.4f;staticfinalfloatLOW_MEMORY_MAX_SIZE_MULTIPLIER=0.33f;// 4MB.staticfinalintARRAY_POOL_SIZE_BYTES=4*1024*1024;@SyntheticfinalContextcontext;// Modifiable (non-final) for testing.@SyntheticActivityManageractivityManager;@SyntheticScreenDimensionsscreenDimensions;@SyntheticfloatmemoryCacheScreens=MEMORY_CACHE_TARGET_SCREENS;@SyntheticfloatbitmapPoolScreens=BITMAP_POOL_TARGET_SCREENS;@SyntheticfloatmaxSizeMultiplier=MAX_SIZE_MULTIPLIER;@SyntheticfloatlowMemoryMaxSizeMultiplier=LOW_MEMORY_MAX_SIZE_MULTIPLIER;@SyntheticintarrayPoolSizeBytes=ARRAY_POOL_SIZE_BYTES;}
interfaceFactory{/** 250 MB of cache. */intDEFAULT_DISK_CACHE_SIZE=250*1024*1024;StringDEFAULT_DISK_CACHE_DIR="image_manager_disk_cache";/** Returns a new disk cache, or {@code null} if no disk cache could be created. */@NullableDiskCachebuild();}
@Deprecated@NonNullprivateRequestManagerfragmentGet(@NonNullContextcontext,@NonNullandroid.app.FragmentManagerfm,@Nullableandroid.app.FragmentparentHint,booleanisParentVisible){//创建RequestManagerFragmentRequestManagerFragmentcurrent=getRequestManagerFragment(fm,parentHint);RequestManagerrequestManager=current.getRequestManager();if(requestManager==null){// TODO(b/27524013): Factor out this Glide.get() call.Glideglide=Glide.get(context);//将Lifecycle和RequestManagerTreeNode传递给RequestManagerrequestManager=factory.build(glide,current.getGlideLifecycle(),current.getRequestManagerTreeNode(),context);// 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){requestManager.onStart();}current.setRequestManager(requestManager);}returnrequestManager;}
privatefinalRunnableaddSelfToLifecycle=newRunnable(){@Overridepublicvoidrun(){lifecycle.addListener(RequestManager.this);}};privatefinalConnectivityMonitorconnectivityMonitor;// Adding default listeners should be much less common than starting new requests. We want// some way of making sure that requests don't mutate our listeners without creating a new copy of// the list each time a request is started.privatefinalCopyOnWriteArrayList<RequestListener<Object>>defaultRequestListeners;@GuardedBy("this")privateRequestOptionsrequestOptions;privatebooleanpauseAllRequestsOnTrimMemoryModerate;publicRequestManager(@NonNullGlideglide,@NonNullLifecyclelifecycle,@NonNullRequestManagerTreeNodetreeNode,@NonNullContextcontext){this(glide,lifecycle,treeNode,newRequestTracker(),glide.getConnectivityMonitorFactory(),context);}// Our usage is safe here.@SuppressWarnings("PMD.ConstructorCallsOverridableMethod")RequestManager(Glideglide,Lifecyclelifecycle,RequestManagerTreeNodetreeNode,RequestTrackerrequestTracker,ConnectivityMonitorFactoryfactory,Contextcontext){this.glide=glide;this.lifecycle=lifecycle;this.treeNode=treeNode;this.requestTracker=requestTracker;this.context=context;connectivityMonitor=factory.build(context.getApplicationContext(),newRequestManagerConnectivityListener(requestTracker));// 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=newCopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());glide.registerRequestManager(this);}
@NonNullpublicViewTarget<ImageView,TranscodeType>into(@NonNullImageViewview){Util.assertMainThread();Preconditions.checkNotNull(view);BaseRequestOptions<?>requestOptions=this;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()){caseCENTER_CROP:requestOptions=requestOptions.clone().optionalCenterCrop();break;caseCENTER_INSIDE:requestOptions=requestOptions.clone().optionalCenterInside();break;caseFIT_CENTER:caseFIT_START:caseFIT_END:requestOptions=requestOptions.clone().optionalFitCenter();break;caseFIT_XY:requestOptions=requestOptions.clone().optionalCenterInside();break;caseCENTER:caseMATRIX:default:// Do nothing.}}returninto(glideContext.buildImageViewTarget(view,transcodeClass),/*targetListener=*/null,requestOptions,Executors.mainThreadExecutor());}
private<YextendsTarget<TranscodeType>>Yinto(@NonNullYtarget,@NullableRequestListener<TranscodeType>targetListener,BaseRequestOptions<?>options,ExecutorcallbackExecutor){Preconditions.checkNotNull(target);if(!isModelSet){thrownewIllegalArgumentException("You must call #load() before calling #into()");}//构建RequestRequestrequest=buildRequest(target,targetListener,options,callbackExecutor);Requestprevious=target.getRequest();if(request.isEquivalentTo(previous)&&!isSkipMemoryCacheWithCompletePreviousRequest(options,previous)){// If the request is completed, beginning again will ensure the result is re-delivered,// triggering RequestListeners and Targets. If the request is failed, beginning again will// restart the request, giving it another chance to complete. If the request is already// running, we can let it continue running without interruption.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();}returntarget;}requestManager.clear(target);target.setRequest(request);//追踪RequestrequestManager.track(target,request);returntarget;}
//从缓存中获取@NullableprivateEngineResource<?>loadFromMemory(EngineKeykey,booleanisMemoryCacheable,longstartTime){//内存缓存不可用直接返回nullif(!isMemoryCacheable){returnnull;}//先从弱引用中获取,如果获取不到则从LruResourceCache中获取缓存EngineResource<?>active=loadFromActiveResources(key);if(active!=null){if(VERBOSE_IS_LOGGABLE){logWithTimeAndKey("Loaded resource from active resources",startTime,key);}returnactive;}EngineResource<?>cached=loadFromCache(key);if(cached!=null){if(VERBOSE_IS_LOGGABLE){logWithTimeAndKey("Loaded resource from cache",startTime,key);}returncached;}returnnull;}@NullableprivateEngineResource<?>loadFromActiveResources(Keykey){//从弱引用中获取EngineResource<?>active=activeResources.get(key);if(active!=null){active.acquire();}returnactive;}privateEngineResource<?>loadFromCache(Keykey){EngineResource<?>cached=getEngineResourceFromCache(key);if(cached!=null){cached.acquire();activeResources.activate(key,cached);}returncached;}privateEngineResource<?>getEngineResourceFromCache(Keykey){//从LruResourceCache中获取缓存Resource<?>cached=cache.remove(key);finalEngineResource<?>result;if(cached==null){result=null;}elseif(cachedinstanceofEngineResource){// Save an object allocation if we've cached an EngineResource (the typical case).result=(EngineResource<?>)cached;}else{result=newEngineResource<>(cached,/*isMemoryCacheable=*/true,/*isRecyclable=*/true,key,/*listener=*/this);}returnresult;}//写入缓存@OverridepublicsynchronizedvoidonResourceReleased(KeycacheKey,EngineResource<?>resource){activeResources.deactivate(cacheKey);if(resource.isMemoryCacheable()){cache.put(cacheKey,resource);}else{resourceRecycler.recycle(resource);}}
@NonNullpublic<A>List<ModelLoader<A,?>>getModelLoaders(@NonNullAmodel){List<ModelLoader<A,?>>modelLoaders=getModelLoadersForClass(getClass(model));if(modelLoaders.isEmpty()){thrownewNoModelLoaderAvailableException(model);}intsize=modelLoaders.size();booleanisEmpty=true;List<ModelLoader<A,?>>filteredLoaders=Collections.emptyList();//noinspection ForLoopReplaceableByForEach to improve perffor(inti=0;i<size;i++){ModelLoader<A,?>loader=modelLoaders.get(i);if(loader.handles(model)){if(isEmpty){filteredLoaders=newArrayList<>(size-i);isEmpty=false;}//根据ModelLoader的handles方法,过滤掉不匹配的//假设传入的是url,则过滤掉DataUrlLoaderfilteredLoaders.add(loader);}}if(filteredLoaders.isEmpty()){thrownewNoModelLoaderAvailableException(model,modelLoaders);}returnfilteredLoaders;}
@NonNullsynchronized<Model>List<ModelLoader<Model,?>>build(@NonNullClass<Model>modelClass){try{List<ModelLoader<Model,?>>loaders=newArrayList<>();for(Entry<?,?>entry:entries){// Avoid stack overflow recursively creating model loaders by only creating loaders in// recursive requests if they haven't been created earlier in the chain. For example:// A Uri loader may translate to another model, which in turn may translate back to a Uri.// The original Uri loader won't be provided to the intermediate model loader, although// other Uri loaders will be.if(alreadyUsedEntries.contains(entry)){continue;}//根据ModelClass进行判断if(entry.handles(modelClass)){alreadyUsedEntries.add(entry);//调用Factory创建Loaderloaders.add(this.<Model,Object>build(entry));alreadyUsedEntries.remove(entry);}}returnloaders;}catch(Throwablet){alreadyUsedEntries.clear();throwt;}}
//StringLoader先将String转化为Uri//通过MultiModelLoaderFactory获取一个MultiModelLoader对象//内部调用的MultiModelLoaderpublicstaticclassStreamFactoryimplementsModelLoaderFactory<String,InputStream>{@NonNull@OverridepublicModelLoader<String,InputStream>build(@NonNullMultiModelLoaderFactorymultiFactory){returnnewStringLoader<>(multiFactory.build(Uri.class,InputStream.class));}@Overridepublicvoidteardown(){// Do nothing.}}
@NonNullpublicsynchronized<Model,Data>ModelLoader<Model,Data>build(@NonNullClass<Model>modelClass,@NonNullClass<Data>dataClass){try{List<ModelLoader<Model,Data>>loaders=newArrayList<>();booleanignoredAnyEntries=false;for(Entry<?,?>entry:entries){// Avoid stack overflow recursively creating model loaders by only creating loaders in// recursive requests if they haven't been created earlier in the chain. For example:// A Uri loader may translate to another model, which in turn may translate back to a Uri.// The original Uri loader won't be provided to the intermediate model loader, although// other Uri loaders will be.if(alreadyUsedEntries.contains(entry)){ignoredAnyEntries=true;continue;}if(entry.handles(modelClass,dataClass)){alreadyUsedEntries.add(entry);loaders.add(this.<Model,Data>build(entry));alreadyUsedEntries.remove(entry);}}//如果存在多个就构建成一个MultiModelLoaderif(loaders.size()>1){returnfactory.build(loaders,throwableListPool);}elseif(loaders.size()==1){returnloaders.get(0);}else{// Avoid crashing if recursion results in no loaders available. The assertion is supposed to// catch completely unhandled types, recursion may mean a subtype isn't handled somewhere// down the stack, which is often ok.if(ignoredAnyEntries){returnemptyModelLoader();}else{thrownewNoModelLoaderAvailableException(modelClass,dataClass);}}}catch(Throwablet){alreadyUsedEntries.clear();throwt;}}
//SingleRequest begin方法if(Util.isValidDimensions(overrideWidth,overrideHeight)){onSizeReady(overrideWidth,overrideHeight);}else{target.getSize(this);}//ViewTarget getSize方法publicvoidgetSize(@NonNullSizeReadyCallbackcb){sizeDeterminer.getSize(cb);}//SizeDeterminer getSize方法voidgetSize(@NonNullSizeReadyCallbackcb){intcurrentWidth=getTargetWidth();//获取宽intcurrentHeight=getTargetHeight();//获取高if(isViewStateAndSizeValid(currentWidth,currentHeight)){cb.onSizeReady(currentWidth,currentHeight);return;}// We want to notify callbacks in the order they were added and we only expect one or two// callbacks to be added a time, so a List is a reasonable choice.if(!cbs.contains(cb)){cbs.add(cb);}if(layoutListener==null){ViewTreeObserverobserver=view.getViewTreeObserver();layoutListener=newSizeDeterminerLayoutListener(this);observer.addOnPreDrawListener(layoutListener);}}//CustomTarget默认是原图大小publicCustomTarget(){this(Target.SIZE_ORIGINAL,Target.SIZE_ORIGINAL);}//Downsampler decodeFromWrappedStreams方法//获取图片的原始宽高int[]sourceDimensions=getDimensions(is,options,callbacks,bitmapPool);intsourceWidth=sourceDimensions[0];intsourceHeight=sourceDimensions[1];//如果设置Target.SIZE_ORIGINAL 则为原始宽高inttargetWidth=requestedWidth==Target.SIZE_ORIGINAL?sourceWidth:requestedWidth;inttargetHeight=requestedHeight==Target.SIZE_ORIGINAL?sourceHeight:requestedHeight;