win8网站设计,生意街创业商机网,网页制作教程古诗词,wordpress创建企业网站Application Options(选项)
Glide允许应用通过AppGlideModule实现完全控制Glide的内存和磁盘应用缓存。Glide对大部分应用提供合理的默认选项#xff0c;部分应用需要定制。
Memory cache#xff08;内存缓存#xff09;自定义MemoryCache的大小
在GlideModule中使用applyOp…Application Options(选项)Glide允许应用通过AppGlideModule实现完全控制Glide的内存和磁盘应用缓存。Glide对大部分应用提供合理的默认选项部分应用需要定制。Memory cache内存缓存自定义MemoryCache的大小在GlideModule中使用applyOptions方法配置MemorySizeCalculatorGlideModule(glideNameGlideApp)publicclassMyGlideModuleextendsAppGlideModule{publicvoidapplyOptions(Contextcontext,GlideBuilderbuilder){MemorySizeCalculatorcalculatornewMemorySizeCalculator.Builder(context).setMemoryCacheScreens(2).build();builder.setMemoryCache(newLruResourceCache(calculator.getMemoryCacheSize()));}}直接覆盖缓存大小GlideModulepublicclassMyGlideModuleextendsAppGlideModule{OverridepublicvoidapplyOptions(Contextcontext,GlideBuilderbuilder){intmemoryCacheSizeBytes1024*1024*10;// 10mbbuilder.setMemoryCache(newLruResourceCache(memoryCacheSizeBytes));}}提供自己的MemoryCache实现GlideModulepublicclassMyGlideModuleextendsAppGlideModule{OverridepublicvoidapplyOptions(Contextcontext,GlideBuilderbuilder){builder.setMemoryCache(newMyMemoryCacheImpl());}}Disk Cache磁盘缓存Glide 使用DiskLruCacheWrapper作为默认的磁盘缓存。 DiskLruCacheWrapper 是一个使用 LRU 算法的固定大小的磁盘缓存。默认磁盘大小为250 MB位置是在应用的缓存文件夹中的一个特定目录。如果显示的媒体是公开的则应用程序可以将位置更改为外部存储GlideModulepublicclassMyGlideModuleextendsAppGlideModule{OverridepublicvoidapplyOptions(Contextcontext,GlideBuilderbuilder){builder.setDiskCache(newExternalCacheDiskCacheFactory(context));}}无论使用内部或外部磁盘存储应用程序都可以改变磁盘缓存的大小GlideModulepublicclassMyGlideModuleextendsAppGlideModule{OverridepublicvoidapplyOptions(Contextcontext,GlideBuilderbuilder){intdiskCacheSizeBytes1024*1024*100;// 100 MBbuilder.setDiskCache(newInternalCacheDiskCacheFactory(context,diskCacheSizeBytes));}}应用程序可以选择DiskCache接口的实现并提供自己的DiskCache.Factory来创建缓存GlideModulepublicclassMyGlideModuleextendsAppGlideModule{OverridepublicvoidapplyOptions(Contextcontext,GlideBuilderbuilder){builder.setDiskCache(newDiskCache.Factory(){OverridepublicDiskCachebuild(){returnnewMyCustomDiskCache();}});}}BitmapPool位图池BitmapPool 是 Glide 内部用于管理和复用Bitmap对象的内存缓存区。它的主要目的是避免频繁创建和销毁Bitmap对象从而减少内存抖动和垃圾回收GC压力显著提升应用在加载大量图片时的流畅性和性能。可以在它们的 AppGlideModule 中定制 BitmapPool 的尺寸使用 applyOptions(Context, GlideBuilder) 方法并配置 MemorySizeCalculatorGlideModulepublicclassMyGlideModuleextendsAppGlideModule{OverridepublicvoidapplyOptions(Contextcontext,GlideBuilderbuilder){MemorySizeCalculatorcalculatornewMemorySizeCalculator.Builder(context).setBitmapPoolScreens(3).build();builder.setBitmapPool(newLruBitmapPool(calculator.getBitmapPoolSize()));}}直接复写这个池的大小GlideModulepublicclassMyGlideModuleextendsAppGlideModule{OverridepublicvoidapplyOptions(Contextcontext,GlideBuilderbuilder){intbitmapPoolSizeBytes1024*1024*30;// 30mbbuilder.setBitmapPool(newLruBitmapPool(bitmapPoolSizeBytes));}}提供自己的BitmapPool实现GlideModulepublicclassMyGlideModuleextendsAppGlideModule{OverridepublicvoidapplyOptions(Contextcontext,GlideBuilderbuilder){builder.setBitmapPool(newMyBitmapPoolImpl());}}缓存机制默认情况下Glide会在开始一个新的图片的请求之前检查以下多级的缓存活动资源Activity Resources现在是否有另一个View正在展示这张图片内存缓存Memory cache该图片是否最近被加载过并存于内存资源缓存Resource该图片是否之前被解码、转换并写入磁盘缓存数据来源Data构建这个图片的资源是否之前曾被写入过文件缓存如果四个步骤都未找到图片则Glide会返回到原始资源以取回数据三级缓存内存缓存优先加载速度最快本地缓存其次加载速度快网络缓存最后加载速度慢浪费流量Glide使用了ActiveResource活动缓存弱引用MemoryCache内存缓存Lru算法DiskCache磁盘缓存Lru算法ActivityResources存储当前界面使用的图片。界面不展示后该Bitmap被缓存至MemoryCache并从ActiveResources中删除Memory Cache存储当前没有使用到的Bitmap当从MemoryCache中得到后被存储到ActiveResources中并从MemoryCache中删除Disk Cache持久缓存图片被处理后会缓存到文件中应用再次被打开时可以加载缓存直接使用注意ActiveResourceMemoryCache属于内存缓存二者不共存应用杀死后不存在配置缓存磁盘缓存策略DiskCacheStrategy可被diskCacheStrategy方法应用到每一个单独的请求。目前支持的策略允许阻止加载过程使用或写入磁盘缓存选择性的仅缓存无修改的原生数据或仅缓存变换过的缩略图或二者都有。指定DiskCacheStrategyGlide.with(this).load(uri).diskCacheStrategy(DiskCacheStrategy.ALL).into(imageView);diskCacheStrategy方法可传入的参数有五种DiskCacheStrategy.ALL既缓存原始图片也缓存转换后的图片DiskCacheStrategy.NONE不缓存任何内容DiskCacheStrategy.DATA只缓存原始图片DiskCacheStrategy.RESULT只缓存转换后的图片仅从缓存加载图片实现图片不在缓存中则加载直接失败可以在单个请求的基础上使用onlyRetrieveFromCache方法Glide.with(this).load(uri).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).onlyRetrieveFromCache(true);.into(imageView);跳过缓存确保一个特定的请求跳过磁盘或内存缓存。仅跳过内存缓存使用skipMemoryCache方法Glide.with(fragment).load(url).skipMemoryCache(true).into(imageView);仅跳过磁盘缓存使用DiskCacheStrategy.NONEGlide.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.NONE).into(imageView);以上两个选项可以同时使用清理磁盘缓存要尝试清理所有磁盘缓存条目可使用clearDiskCachenewThread(newRunnable(){Overridepublicvoidrun(){try{// 必须在子线程上调用此方法。Glide.get(AppGlobalUtils.getApplication()).clearDiskCache();}catch(Exceptione){e.printStackTrace();}}}).start();Glide源码分析加载流程Engine类负责启动加载并管理活动资源和缓存资源其中的load方法提供路径加载图片publicRLoadStatusload(GlideContextglideContext,Objectmodel,Keysignature,intwidth,intheight,Class?resourceClass,ClassRtranscodeClass,Prioritypriority,DiskCacheStrategydiskCacheStrategy,MapClass?,Transformation?transformations,booleanisTransformationRequired,booleanisScaleOnlyOrNoTransform,Optionsoptions,booleanisMemoryCacheable,booleanuseUnlimitedSourceExecutorPool,booleanuseAnimationPool,booleanonlyRetrieveFromCache,ResourceCallbackcb,ExecutorcallbackExecutor){longstartTimeVERBOSE_IS_LOGGABLE?LogTime.getLogTime():0;//EngineKey用于多路传输加载的仅内存缓存密钥EngineKeykeykeyFactory.buildKey(model,signature,width,height,transformations,resourceClass,transcodeClass,options);EngineResource?memoryResource;synchronized(this){//重点调用了loadFromMemory方法memoryResourceloadFromMemory(key,isMemoryCacheable,startTime);if(memoryResourcenull){returnwaitForExistingOrStartNewJob(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);returnnull;}下面来看loadFromMemory()NullableprivateEngineResource?loadFromMemory(EngineKeykey,booleanisMemoryCacheable,longstartTime){if(!isMemoryCacheable){returnnull;}//根据key去活动缓存中找EngineResource?activeloadFromActiveResources(key);if(active!null){if(VERBOSE_IS_LOGGABLE){logWithTimeAndKey(Loaded resource from active resources,startTime,key);}//找到了直接返回数据returnactive;}//找不到接着去内存缓存中找EngineResource?cachedloadFromCache(key);if(cached!null){if(VERBOSE_IS_LOGGABLE){logWithTimeAndKey(Loaded resource from cache,startTime,key);}returncached;}returnnull;}之后我们分别来看活动缓存和内存缓存活动缓存privateEngineResource?loadFromActiveResources(Keykey){// activeResources活动缓存EngineResource?activeactiveResources.get(key);if(active!null){active.acquire();}returnactive;}NullablesynchronizedEngineResource?get(Keykey){//弱引用ResourceWeakReferenceactiveRefactiveEngineResources.get(key);if(activeRefnull){returnnull;}EngineResource?activeactiveRef.get();if(activenull){cleanupActiveReference(activeRef);}returnactive;}SyntheticvoidcleanupActiveReference(NonNullResourceWeakReferenceref){synchronized(this){//从活动缓存中删除资源activeEngineResources.remove(ref.key);if(!ref.isCacheable||ref.resourcenull){return;}}EngineResource?newResourcenewEngineResource(ref.resource,/*isMemoryCacheable*/true,/*isRecyclable*/false,ref.key,listener);listener.onResourceReleased(ref.key,newResource);}OverridepublicvoidonResourceReleased(KeycacheKey,EngineResource?resource){activeResources.deactivate(cacheKey);if(resource.isMemoryCacheable()){//将活动缓存数据写入内存缓存cache.put(cacheKey,resource);}else{resourceRecycler.recycle(resource,/*forceNextFrame*/false);}}内存缓存privateEngineResource?loadFromCache(Keykey){//从内存缓存中删除数据EngineResource?cachedgetEngineResourceFromCache(key);if(cached!null){cached.acquire();//将数据保存至活动缓存activeResources.activate(key,cached);}returncached;}privateEngineResource?getEngineResourceFromCache(Keykey){//cacheMemoryCache类型Resource?cachedcache.remove(key);finalEngineResource?result;if(cachednull){resultnull;}elseif(cachedinstanceofEngineResource){// Save an object allocation if weve cached an EngineResource (the typical case).result(EngineResource?)cached;}else{resultnewEngineResource(cached,/*isMemoryCacheable*/true,/*isRecyclable*/true,key,/*listener*/this);}returnresult;}如果两种缓存都未找到说明图片未保存就会调用waitForExistingOrStartNewJob方法privateRLoadStatuswaitForExistingOrStartNewJob(...){//通过添加和删除加载的回调并通知来管理加载的类在加载完成时回调EngineJob?currentjobs.get(key,onlyRetrieveFromCache);if(current!null){current.addCallback(cb,callbackExecutor);if(VERBOSE_IS_LOGGABLE){logWithTimeAndKey(Added to existing load,startTime,key);}returnnewLoadStatus(cb,current);}EngineJobRengineJobengineJobFactory.build(key,isMemoryCacheable,useUnlimitedSourceExecutorPool,useAnimationPool,onlyRetrieveFromCache);//负责从缓存数据或原始源解码资源的类DecodeJobRdecodeJobdecodeJobFactory.build(glideContext,model,key,signature,width,height,resourceClass,transcodeClass,priority,diskCacheStrategy,transformations,isTransformationRequired,isScaleOnlyOrNoTransform,onlyRetrieveFromCache,options,engineJob);jobs.put(key,engineJob);engineJob.addCallback(cb,callbackExecutor);engineJob.start(decodeJob);if(VERBOSE_IS_LOGGABLE){logWithTimeAndKey(Started new load,startTime,key);}returnnewLoadStatus(cb,engineJob);}classDecodeJobRimplementsDataFetcherGenerator.FetcherReadyCallback,Runnable,ComparableDecodeJob?,Poolable{}...//DiskCacheProvider跟磁盘缓存有关DecodeJob(DiskCacheProviderdiskCacheProvider,Pools.PoolDecodeJob?pool){this.diskCacheProviderdiskCacheProvider;this.poolpool;}...LRU算法近期最少使用算法核心思想就是当缓存满时淘汰最少使用的缓存对象实现内存缓存的LruCache和硬盘缓存的DisLruCache的核心思想都是LRU缓存算法。