2023年6月21日发(作者:)
Android中Glide加载库的图⽚缓存配置究极指南零、选择Glide为什么图⽚加载我⾸先推荐Glide?图⽚加载框架⽤了不少,从afinal框架的afinalBitmap,Xutils的BitmapUtils,⽼牌框架universalImageLoader,著名开源组织square的picasso,google推荐的glide到FaceBook推出的fresco。这些我前前后后都体验过,那么⾯对这么多的框架,该如何选择呢?下⾯简单分析下我的看法。afinal和Xuils在github上作者已经停⽌维护了,开源社区最新的框架要属KJFramework,不过这种快速开发框架看似很好⽤,功能也应有尽有,⼩型项⽬也罢,⼤型项⽬我不是很推荐,这样做项⽬的耦合度太⾼,⼀旦出现停⽌维护,⽽新的问题不断增加,没⼈处理就⿇烦了。在glide和fresco还未出来的时候,当时最⽕的莫过于universalImageLoader和picasso了,当时觉得universalImageLoader配置相对picasso⿇烦,虽然提供了各种配置,但是没有实践过,根本不知道如何配置,还不如都采⽤默认配置,就选择了picasso作为图⽚加载框架,⽤了近⼀年的时间,没有太⼤的问题,且使⽤简单,或许是因为之前的项⽬太过于简单,周期也并不是很长,还有使⽤eclipse开发,⼀个很⼤的问题⼀直都没有暴露出来,换上了最新的Android Studio可以清晰的看到各种性能相关的监控,如cpu还有内存监控,终于知道了之前做的项⽬都那么的卡顿的罪魁祸⾸,picasso加载稍微⼤⼀点的图⽚就特别耗内存,通常⼀个listView或者顶部滑动⼴告栏都含有多张图⽚,这使得做出的页⾯只要含图⽚较多就异常卡顿(之前的时候还把它归结为测试机不好),知道这⼀点后我就有点想把picasso给替换掉,但这⼀次我不能那么粗⼼。测试了picasso,glide,universalImageLoader,fresco这四个框架,测试内容⼤概有以下⼏项,内存测试,⼤图⽚测试,⼩图⽚测试,本地图⽚,⽹络图⽚当然还结合官⽅⽂档体验其特⾊功能,内存测试中,glide,universalImageLoader,fresco表现都⾮常优秀,picasso这⼀点上实在是太糟糕了,⼩图⽚差别也不是很⼤,稍微⼤点图⽚内存消耗就要⽐其他⾼出⼏倍,这⼀点上证明了我的猜想,picasso不能再⽤了,下⾯⼀项项分析其他框架,在⾼于2M左右⼤图测试中fresco的表现则和picasso⼀样直接神马都不显⽰,项⽬中要实现⼤图预览功能,这点上是不⾏的,接着看universalImageLoader和glide在这⼏项测试中成绩都很好,到底该如何选择呢?因为我项⽬之前⽤的picasso,glide从⽤法上⼏乎就是另⼀个picasso,从picasso转移到glide相对改动较少,还有⼀点就是这个项⽬是google在维护,我也能给它更多的信任,相⽐较universalImageLoader,glide可以⽀持gif和短视频,后期也需要⽤到,这⾥不得不谈⼀下glide优秀的缓存机制了,glide图⽚缓存默认使⽤RGB565相当于ARGB8888可以节省不少的空间,⽀持与activity,fragment,application⽣命周期的联动,更智能管理图⽚请求当然还有其他的扩展更多可以看?glide介绍?当然,glide的⽅法数量⽐universalImageLoader多了1000多个,遇到64k问题的会⽐较关注这个。刚才只是掠过fresco,其实我对他的期待还是蛮⼤的,因为刚出来还有居多不稳定的地⽅,⾥⾯存在着⼤量吸引着我的功能,⽀持webps格式(和jpg⼀样都是有损压缩格式,webps相同质量图⽚更节省空间),⽀持渐进式jpeg,可以轻松的定制image的各种属性,⽀持多图请求和图⽚复⽤,并⽀持⼿势缩放和旋转等等,更多介绍?fresco,当然,实际⽤的时候并没有那么好,很多功能都有待完善。还有⼀点细节的地⽅要注意的,最好不要直接拿来⽤,⾄少经过⾃⼰简单的封装,⽽不是直接在项⽬中使⽤,⼀个简单的例⼦,后期图⽚过多,可能需要另外配置⼀台机器单独存放图⽚,主机地址做成可配置,可不要因为⼀个简单的需求⼜要加班了更多。⼀、Glide3.0以来的新特性1.动态的GIF图⽚加载:(context).load(...).asBitmap() //显⽰gif静态图⽚(context).load(...).asGif() //显⽰gif动态图⽚2.本地视频快照:Glide现在还可以把视频解码为⼀张图⽚: (context).load(“视频路径“)(经过我的测试,只能把⼿机本地的mp4视频解析为⼀张图⽚,把mp4⽂件放在raw⽂件中,不能解析)3.对缩略图的⽀持: //加载yourView1/10尺⼨的缩略图,然后加载全图(yourFragment).load(yourUrl).thumbnail(0.1f).into(yourView)4.⽣命周期集成同时将Activity/Fragment作为with()参数的好处是:图⽚加载会和Activity/Fragment的⽣命周期保持⼀致,请求会在onStop的时候⾃动暂停,在onStart的时候重新启动,gif的动画也会在onStop的时候停⽌,以免在后台消耗电量。5.转码Glide的.toBytes()和.transcode()⽅法允许在后台获取、解码和转换⼀个图⽚,你可以将⼀张图⽚转换成更多有⽤的图⽚格式,⽐如,上传⼀张250*250的图⽚ (context) .load(“/user/profile/photo/path”) .asBitmap() .toBytes() .centerCrop() .into(new SimpleTarget
⼆、图⽚的缓存和缓存的时效机制1.图⽚缓存的键值图⽚缓存的键值主要⽤于,Glide当中的键值主要包含三个部分:通过()⽅法返回的String数据作为键值。⼀般的DataFetchers会简单返回数据模型data model的toString()结果,如果是URL/File会返回相应的路径图⽚的尺⼨,主要是通过override(width,height)或者通过Target's getSize()⽅法确定的尺⼨信息包含⼀个可选的签名所有的这些东西会通过⼀种散列算法⽣成⼀个独有、安全的⽂件名,通过此⽂件名将图⽚缓存在disk中2.缓存失效因为Glide当中图⽚缓存key的⽣成是通过⼀个散列算法来实现的,所以很难⼿动去确定哪些⽂件可以从缓存当中进⾏删除2.1 当内容(url,file path)改变的时候,改变相应的标识符就可以了,Glide当中也提供了signature()⽅法,将⼀个附加的数据加⼊到缓存key当中多媒体存储数据,可⽤MediaStoreSignature类作为标识符,会将⽂件的修改时间、mimeType等信息作为cacheKey的⼀部分⽂件,使⽤StringSignatureUrls ,使⽤StringSignature (yourFragment) .load(yourFileDataModel) .signature(new StringSignature(yourVersionMetadata)) .into(yourImageView); (fragment) .load(mediaStoreUri) .signature(new MediaStoreSignature(mimeType, dateModified, orientation)) .into(view);⾃定义标识符: public class IntegerVersionSignature implements Key { private int currentVersion; public IntegerVersionSignature(int currentVersion) { tVersion = currentVersion; } @Override public boolean equals(Object o) { if (o instanceof IntegerVersionSignature) { IntegerVersionSignature other = (IntegerVersionSignature) o; return currentVersion = tVersion; } return false; } @Override public int hashCode() { return currentVersion; } @Override public void updateDiskCacheKey(MessageDigest md) { (te().putInt(signature).array()); }}2.2、不缓存可以通过diskCacheStrategy(.)实现
三、配置GlideModules可以通过GlideModule接⼝来配置Glide的配置⽂件,并且像ModelLoaders⼀样注册相关组件。包含⼀个GlideMode :第⼀步、To use and register a GlideModule, first implement the interface with your configuration and components: public class MyGlideModule implements GlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { // Apply options to the builder here. } @Override public void registerComponents(Context context, Glide glide) { // register ModelLoaders here. }}第⼆步、然后将上⾯的实现了加⼊到当中: -keepnames class * eModule第三步、在⽂件中添加meta-data,以便Glide能够找到你的Module
五、GlideModules冲突虽然Glide允许⼀个应⽤当中存在多个GlideModules,Glide并不会按照⼀个特殊的顺序去调⽤已注册的GlideModules,如果⼀个应⽤的多个依赖⼯程当中有多个相同的Modules,就有可能会产⽣冲突。如果⼀个冲突是不可避免的,应⽤应该默认去定义⼀个⾃⼰的Module,⽤来⼿动地处理这个冲突,在进⾏Manifest合并的时候,可以⽤下⾯的标签排除冲突的module。
// Careful: the external cache directory doesn't enforce permissions File cacheLocation = new File(ernalCacheDir(), "cache_dir_name"); (); return (cacheLocation, yourSizeInBytes); } });2.内存当中的缓存和POOLSGlideBuilder当中,允许开发者去设置内存当中图⽚缓存区的⼤⼩,主要涉及到的类包括MemoryCache和BitmapPool2.1 ⼤⼩的设置默认内存缓存的⼤⼩是⽤过MemorySizeCalculator来实现的,这个类会根据设备屏幕的⼤⼩,计算出⼀个合适的size,开发者可以获取到相关的默认设置信息: MemorySizeCalculator calculator = new MemorySizeCalculator(context);int defaultMemoryCacheSize = oryCacheSize();int defaultBitmapPoolSize = mapPoolSize();如果在应⽤当中想要调整内存缓存的⼤⼩,开发者可以通过如下⽅式:(context).setMemoryCategory();2.2 Memory CacheGlide内存缓存的⽬的是减少I/O,提⾼效率可以通过GlideBuidler的setMemoryCache(MemoryCache memoryCache)去设置缓存的⼤⼩,开发者可以通过LruResourceCache类去设置缓存区的⼤⼩oryCache(new LruResourceCache(yourSizeInBytes));2.3 Bitmap Pool可以通过GlideBuilder的setBitmapPool()⽅法设置池⼦的⼤⼩,LruBitmapPool是Glide的默认实现,使⽤如下: mapPool(new LruBitmapPool(sizeInBytes));.图⽚格式GlideBuilder允许开发者设置⼀个全局的默认图⽚格式,在默认情况下,Glide使⽤RGB_565格式加载图⽚,如果想要使⽤⾼质量的图⽚,可以通过如下⽅式设置系统的图⽚格式:
odeFormat(_ARGB_8888);七、⾃定义显⽰控件除了可以将图⽚、视频快照和GIFS显⽰在View上⾯之外,开发者也可以在⾃定义的Target上⾯显⽰这些媒体⽂件Target重点内容如果你想简单地加载⼀个Bitmap,你可以通过以下简单的⽅式⽽不是直接地显⽰给⽤户,可能是显⽰⼀个notification,或者上传⼀个头像,Glide都能很好地实现SimpleTarget提供了对Target的简单实现,并且让你专注于对加载结果的处理为了使⽤SimpleTarget,开发者需要提供⼀个宽和⾼的像素值,⽤来加载你的资源⽂件,并且你需要去实现 onResourceReady(R resource,GlideAnimation super R> glideAnimation)int myWidth = 512;int myHeight = 384;(yourApplicationContext)) .load(youUrl) .asBitmap() .into(new SimpleTarget
@Override public void onGenerated(Palette palette) { // Here's your generated palette } }); } });⼋、使⽤Glide下载⾃定义尺⼨的图⽚Glide的ModelLoader接⼝为开发者提供了装载图⽚的view的尺⼨,并且允许开发者使⽤这些尺⼨信息去选择合适的URL去下载图⽚。选⽤适当的尺⼨可以节省宽带和设备的空间开销,提⾼app的性能1、通过http/https下载图⽚,可以通过继承BaseGlideUtlLoader来实现: public interface MyDataModel { public String buildUrl(int width, int height);}
public class MyUrlLoader extends BaseGlideUrlLoader
new y()); }}这样你就可以跳过.using()了 (yourFragment) .load(yourModel) .into(yourView);九、集成库1.什么是集成库Glide包含⼀些⼩的、可选的集成库,⽬前Glide集成库当中包含了访问⽹络操作的Volley和OkHttp2.为什么要包含集成库这些集成库,和Glide的ModelLoader系统允许开发者使⽤⼀致地框架去进⾏⽹络相关的操作3.如何将⼀个库集成到Glide当中,将⼀个库集成到Glide当中需要两步操作,包含正确的dependency,确保创建了该集成库的GlideModule,⽐如,将Volley集成到Glide当中第⼀步、添加依赖 dependencies { compile ':volley-integration:1.2.2' compile ':library:1.0.5'}第⼆步、创建Volley集成库的GlideModule
(yourFragment) .load(yourUrl) .fitCenter() .into(yourView); (yourFragment) .load(yourUrl) .centerCrop() .into(yourView); // For Bitmaps:(yourFragment) .load(yourUrl) .asBitmap() .centerCrop() .into(yourView);// For gifs:(yourFragment) .load(yourUrl) .asGif() .fitCenter() .into(yourView);甚⾄可以在两幅图⽚进⾏类型转换的时候进⾏transformed (yourFragment) .load(yourUrl) .asBitmap() .toBytes() .centerCrop() .into(new SimpleTarget
private static class MyTransformation extends BitmapTransformation { public MyTransformation(Context context) { super(context); } @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform,
int outWidth, int outHeight) { Bitmap myTransformedBitmap = ... // apply some transformation here. return myTransformedBitmap; } @Override public String getId() { // Return some id that uniquely identifies your transformation. return "sformation"; }}第⼆步、在Glide⽅法链当中⽤.transform(…)替换fitCenter()/centerCrop() (yourFragment) .load(yourUrl) .transform(new MyTransformation(context)) .into(yourView);// For Bitmaps:(yourFragment) .load(yourUrl) .asBitmap() .transform(new MyTransformation(context)) .into(yourView);// For Gifs:(yourFragment) .load(yourUrl) .asGif() .transform(new MyTransformation(context)) .into(yourView);3.⾃定义转换器的尺⼨在上⾯使⽤过程当中没有设置尺⼨值,那么转换器转换的图⽚尺⼨怎么确定呢,Glide实际上已经⾜够智能根据view的尺⼨来确定转换图⽚的尺⼨了如果需要⾃定义尺⼨,⽽不是⽤view和target当中的尺⼨,那么可以使⽤override(int,int)设置相关的宽和⾼4. Bitmap 再利⽤为了减少垃圾收集,可以通过BitmapPool接⼝去释放不需要的Bitmaps,当然也可以对⾥⾯的bitmap进⾏再利⽤。例如在⼀次转换中,从pool当中得到⼀个bitmap将Bitmap回设给Canvas使⽤Matrix、Paint在Canvas上⾯绘制原始的Bitmap,或者通过⼀个Shader来转换⼀个image4.1 不要⼿动地去释放⼀个转换的bitmap资源,也不要将transform()之后的Bitmap重新放置到BitmapPool当中去 protected Bitmap transform(BitmapPool bitmapPool, Bitmap original, int width, int height) { Bitmap result = (width, height, _8888); // If no matching Bitmap is in the pool, get will return null, so we should //allocate. if (result == null) { // Use ARGB_8888 since we're going to add alpha to the image. result = Bitmap(width, height, _8888); } // Create a Canvas backed by the result Bitmap. Canvas canvas = new Canvas(result); Paint paint = new Paint(); ha(128); // Draw the original Bitmap onto the result Bitmap with a transformation. tmap(original, 0, 0, paint); // Since we've replaced our original Bitmap, we return our new Bitmap here. Glide will // will take care of returning our original Bitmap to the BitmapPool for us.
return result;}
2023年6月21日发(作者:)
Android中Glide加载库的图⽚缓存配置究极指南零、选择Glide为什么图⽚加载我⾸先推荐Glide?图⽚加载框架⽤了不少,从afinal框架的afinalBitmap,Xutils的BitmapUtils,⽼牌框架universalImageLoader,著名开源组织square的picasso,google推荐的glide到FaceBook推出的fresco。这些我前前后后都体验过,那么⾯对这么多的框架,该如何选择呢?下⾯简单分析下我的看法。afinal和Xuils在github上作者已经停⽌维护了,开源社区最新的框架要属KJFramework,不过这种快速开发框架看似很好⽤,功能也应有尽有,⼩型项⽬也罢,⼤型项⽬我不是很推荐,这样做项⽬的耦合度太⾼,⼀旦出现停⽌维护,⽽新的问题不断增加,没⼈处理就⿇烦了。在glide和fresco还未出来的时候,当时最⽕的莫过于universalImageLoader和picasso了,当时觉得universalImageLoader配置相对picasso⿇烦,虽然提供了各种配置,但是没有实践过,根本不知道如何配置,还不如都采⽤默认配置,就选择了picasso作为图⽚加载框架,⽤了近⼀年的时间,没有太⼤的问题,且使⽤简单,或许是因为之前的项⽬太过于简单,周期也并不是很长,还有使⽤eclipse开发,⼀个很⼤的问题⼀直都没有暴露出来,换上了最新的Android Studio可以清晰的看到各种性能相关的监控,如cpu还有内存监控,终于知道了之前做的项⽬都那么的卡顿的罪魁祸⾸,picasso加载稍微⼤⼀点的图⽚就特别耗内存,通常⼀个listView或者顶部滑动⼴告栏都含有多张图⽚,这使得做出的页⾯只要含图⽚较多就异常卡顿(之前的时候还把它归结为测试机不好),知道这⼀点后我就有点想把picasso给替换掉,但这⼀次我不能那么粗⼼。测试了picasso,glide,universalImageLoader,fresco这四个框架,测试内容⼤概有以下⼏项,内存测试,⼤图⽚测试,⼩图⽚测试,本地图⽚,⽹络图⽚当然还结合官⽅⽂档体验其特⾊功能,内存测试中,glide,universalImageLoader,fresco表现都⾮常优秀,picasso这⼀点上实在是太糟糕了,⼩图⽚差别也不是很⼤,稍微⼤点图⽚内存消耗就要⽐其他⾼出⼏倍,这⼀点上证明了我的猜想,picasso不能再⽤了,下⾯⼀项项分析其他框架,在⾼于2M左右⼤图测试中fresco的表现则和picasso⼀样直接神马都不显⽰,项⽬中要实现⼤图预览功能,这点上是不⾏的,接着看universalImageLoader和glide在这⼏项测试中成绩都很好,到底该如何选择呢?因为我项⽬之前⽤的picasso,glide从⽤法上⼏乎就是另⼀个picasso,从picasso转移到glide相对改动较少,还有⼀点就是这个项⽬是google在维护,我也能给它更多的信任,相⽐较universalImageLoader,glide可以⽀持gif和短视频,后期也需要⽤到,这⾥不得不谈⼀下glide优秀的缓存机制了,glide图⽚缓存默认使⽤RGB565相当于ARGB8888可以节省不少的空间,⽀持与activity,fragment,application⽣命周期的联动,更智能管理图⽚请求当然还有其他的扩展更多可以看?glide介绍?当然,glide的⽅法数量⽐universalImageLoader多了1000多个,遇到64k问题的会⽐较关注这个。刚才只是掠过fresco,其实我对他的期待还是蛮⼤的,因为刚出来还有居多不稳定的地⽅,⾥⾯存在着⼤量吸引着我的功能,⽀持webps格式(和jpg⼀样都是有损压缩格式,webps相同质量图⽚更节省空间),⽀持渐进式jpeg,可以轻松的定制image的各种属性,⽀持多图请求和图⽚复⽤,并⽀持⼿势缩放和旋转等等,更多介绍?fresco,当然,实际⽤的时候并没有那么好,很多功能都有待完善。还有⼀点细节的地⽅要注意的,最好不要直接拿来⽤,⾄少经过⾃⼰简单的封装,⽽不是直接在项⽬中使⽤,⼀个简单的例⼦,后期图⽚过多,可能需要另外配置⼀台机器单独存放图⽚,主机地址做成可配置,可不要因为⼀个简单的需求⼜要加班了更多。⼀、Glide3.0以来的新特性1.动态的GIF图⽚加载:(context).load(...).asBitmap() //显⽰gif静态图⽚(context).load(...).asGif() //显⽰gif动态图⽚2.本地视频快照:Glide现在还可以把视频解码为⼀张图⽚: (context).load(“视频路径“)(经过我的测试,只能把⼿机本地的mp4视频解析为⼀张图⽚,把mp4⽂件放在raw⽂件中,不能解析)3.对缩略图的⽀持: //加载yourView1/10尺⼨的缩略图,然后加载全图(yourFragment).load(yourUrl).thumbnail(0.1f).into(yourView)4.⽣命周期集成同时将Activity/Fragment作为with()参数的好处是:图⽚加载会和Activity/Fragment的⽣命周期保持⼀致,请求会在onStop的时候⾃动暂停,在onStart的时候重新启动,gif的动画也会在onStop的时候停⽌,以免在后台消耗电量。5.转码Glide的.toBytes()和.transcode()⽅法允许在后台获取、解码和转换⼀个图⽚,你可以将⼀张图⽚转换成更多有⽤的图⽚格式,⽐如,上传⼀张250*250的图⽚ (context) .load(“/user/profile/photo/path”) .asBitmap() .toBytes() .centerCrop() .into(new SimpleTarget
⼆、图⽚的缓存和缓存的时效机制1.图⽚缓存的键值图⽚缓存的键值主要⽤于,Glide当中的键值主要包含三个部分:通过()⽅法返回的String数据作为键值。⼀般的DataFetchers会简单返回数据模型data model的toString()结果,如果是URL/File会返回相应的路径图⽚的尺⼨,主要是通过override(width,height)或者通过Target's getSize()⽅法确定的尺⼨信息包含⼀个可选的签名所有的这些东西会通过⼀种散列算法⽣成⼀个独有、安全的⽂件名,通过此⽂件名将图⽚缓存在disk中2.缓存失效因为Glide当中图⽚缓存key的⽣成是通过⼀个散列算法来实现的,所以很难⼿动去确定哪些⽂件可以从缓存当中进⾏删除2.1 当内容(url,file path)改变的时候,改变相应的标识符就可以了,Glide当中也提供了signature()⽅法,将⼀个附加的数据加⼊到缓存key当中多媒体存储数据,可⽤MediaStoreSignature类作为标识符,会将⽂件的修改时间、mimeType等信息作为cacheKey的⼀部分⽂件,使⽤StringSignatureUrls ,使⽤StringSignature (yourFragment) .load(yourFileDataModel) .signature(new StringSignature(yourVersionMetadata)) .into(yourImageView); (fragment) .load(mediaStoreUri) .signature(new MediaStoreSignature(mimeType, dateModified, orientation)) .into(view);⾃定义标识符: public class IntegerVersionSignature implements Key { private int currentVersion; public IntegerVersionSignature(int currentVersion) { tVersion = currentVersion; } @Override public boolean equals(Object o) { if (o instanceof IntegerVersionSignature) { IntegerVersionSignature other = (IntegerVersionSignature) o; return currentVersion = tVersion; } return false; } @Override public int hashCode() { return currentVersion; } @Override public void updateDiskCacheKey(MessageDigest md) { (te().putInt(signature).array()); }}2.2、不缓存可以通过diskCacheStrategy(.)实现
三、配置GlideModules可以通过GlideModule接⼝来配置Glide的配置⽂件,并且像ModelLoaders⼀样注册相关组件。包含⼀个GlideMode :第⼀步、To use and register a GlideModule, first implement the interface with your configuration and components: public class MyGlideModule implements GlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { // Apply options to the builder here. } @Override public void registerComponents(Context context, Glide glide) { // register ModelLoaders here. }}第⼆步、然后将上⾯的实现了加⼊到当中: -keepnames class * eModule第三步、在⽂件中添加meta-data,以便Glide能够找到你的Module
五、GlideModules冲突虽然Glide允许⼀个应⽤当中存在多个GlideModules,Glide并不会按照⼀个特殊的顺序去调⽤已注册的GlideModules,如果⼀个应⽤的多个依赖⼯程当中有多个相同的Modules,就有可能会产⽣冲突。如果⼀个冲突是不可避免的,应⽤应该默认去定义⼀个⾃⼰的Module,⽤来⼿动地处理这个冲突,在进⾏Manifest合并的时候,可以⽤下⾯的标签排除冲突的module。
// Careful: the external cache directory doesn't enforce permissions File cacheLocation = new File(ernalCacheDir(), "cache_dir_name"); (); return (cacheLocation, yourSizeInBytes); } });2.内存当中的缓存和POOLSGlideBuilder当中,允许开发者去设置内存当中图⽚缓存区的⼤⼩,主要涉及到的类包括MemoryCache和BitmapPool2.1 ⼤⼩的设置默认内存缓存的⼤⼩是⽤过MemorySizeCalculator来实现的,这个类会根据设备屏幕的⼤⼩,计算出⼀个合适的size,开发者可以获取到相关的默认设置信息: MemorySizeCalculator calculator = new MemorySizeCalculator(context);int defaultMemoryCacheSize = oryCacheSize();int defaultBitmapPoolSize = mapPoolSize();如果在应⽤当中想要调整内存缓存的⼤⼩,开发者可以通过如下⽅式:(context).setMemoryCategory();2.2 Memory CacheGlide内存缓存的⽬的是减少I/O,提⾼效率可以通过GlideBuidler的setMemoryCache(MemoryCache memoryCache)去设置缓存的⼤⼩,开发者可以通过LruResourceCache类去设置缓存区的⼤⼩oryCache(new LruResourceCache(yourSizeInBytes));2.3 Bitmap Pool可以通过GlideBuilder的setBitmapPool()⽅法设置池⼦的⼤⼩,LruBitmapPool是Glide的默认实现,使⽤如下: mapPool(new LruBitmapPool(sizeInBytes));.图⽚格式GlideBuilder允许开发者设置⼀个全局的默认图⽚格式,在默认情况下,Glide使⽤RGB_565格式加载图⽚,如果想要使⽤⾼质量的图⽚,可以通过如下⽅式设置系统的图⽚格式:
odeFormat(_ARGB_8888);七、⾃定义显⽰控件除了可以将图⽚、视频快照和GIFS显⽰在View上⾯之外,开发者也可以在⾃定义的Target上⾯显⽰这些媒体⽂件Target重点内容如果你想简单地加载⼀个Bitmap,你可以通过以下简单的⽅式⽽不是直接地显⽰给⽤户,可能是显⽰⼀个notification,或者上传⼀个头像,Glide都能很好地实现SimpleTarget提供了对Target的简单实现,并且让你专注于对加载结果的处理为了使⽤SimpleTarget,开发者需要提供⼀个宽和⾼的像素值,⽤来加载你的资源⽂件,并且你需要去实现 onResourceReady(R resource,GlideAnimation super R> glideAnimation)int myWidth = 512;int myHeight = 384;(yourApplicationContext)) .load(youUrl) .asBitmap() .into(new SimpleTarget
@Override public void onGenerated(Palette palette) { // Here's your generated palette } }); } });⼋、使⽤Glide下载⾃定义尺⼨的图⽚Glide的ModelLoader接⼝为开发者提供了装载图⽚的view的尺⼨,并且允许开发者使⽤这些尺⼨信息去选择合适的URL去下载图⽚。选⽤适当的尺⼨可以节省宽带和设备的空间开销,提⾼app的性能1、通过http/https下载图⽚,可以通过继承BaseGlideUtlLoader来实现: public interface MyDataModel { public String buildUrl(int width, int height);}
public class MyUrlLoader extends BaseGlideUrlLoader
new y()); }}这样你就可以跳过.using()了 (yourFragment) .load(yourModel) .into(yourView);九、集成库1.什么是集成库Glide包含⼀些⼩的、可选的集成库,⽬前Glide集成库当中包含了访问⽹络操作的Volley和OkHttp2.为什么要包含集成库这些集成库,和Glide的ModelLoader系统允许开发者使⽤⼀致地框架去进⾏⽹络相关的操作3.如何将⼀个库集成到Glide当中,将⼀个库集成到Glide当中需要两步操作,包含正确的dependency,确保创建了该集成库的GlideModule,⽐如,将Volley集成到Glide当中第⼀步、添加依赖 dependencies { compile ':volley-integration:1.2.2' compile ':library:1.0.5'}第⼆步、创建Volley集成库的GlideModule
(yourFragment) .load(yourUrl) .fitCenter() .into(yourView); (yourFragment) .load(yourUrl) .centerCrop() .into(yourView); // For Bitmaps:(yourFragment) .load(yourUrl) .asBitmap() .centerCrop() .into(yourView);// For gifs:(yourFragment) .load(yourUrl) .asGif() .fitCenter() .into(yourView);甚⾄可以在两幅图⽚进⾏类型转换的时候进⾏transformed (yourFragment) .load(yourUrl) .asBitmap() .toBytes() .centerCrop() .into(new SimpleTarget
private static class MyTransformation extends BitmapTransformation { public MyTransformation(Context context) { super(context); } @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform,
int outWidth, int outHeight) { Bitmap myTransformedBitmap = ... // apply some transformation here. return myTransformedBitmap; } @Override public String getId() { // Return some id that uniquely identifies your transformation. return "sformation"; }}第⼆步、在Glide⽅法链当中⽤.transform(…)替换fitCenter()/centerCrop() (yourFragment) .load(yourUrl) .transform(new MyTransformation(context)) .into(yourView);// For Bitmaps:(yourFragment) .load(yourUrl) .asBitmap() .transform(new MyTransformation(context)) .into(yourView);// For Gifs:(yourFragment) .load(yourUrl) .asGif() .transform(new MyTransformation(context)) .into(yourView);3.⾃定义转换器的尺⼨在上⾯使⽤过程当中没有设置尺⼨值,那么转换器转换的图⽚尺⼨怎么确定呢,Glide实际上已经⾜够智能根据view的尺⼨来确定转换图⽚的尺⼨了如果需要⾃定义尺⼨,⽽不是⽤view和target当中的尺⼨,那么可以使⽤override(int,int)设置相关的宽和⾼4. Bitmap 再利⽤为了减少垃圾收集,可以通过BitmapPool接⼝去释放不需要的Bitmaps,当然也可以对⾥⾯的bitmap进⾏再利⽤。例如在⼀次转换中,从pool当中得到⼀个bitmap将Bitmap回设给Canvas使⽤Matrix、Paint在Canvas上⾯绘制原始的Bitmap,或者通过⼀个Shader来转换⼀个image4.1 不要⼿动地去释放⼀个转换的bitmap资源,也不要将transform()之后的Bitmap重新放置到BitmapPool当中去 protected Bitmap transform(BitmapPool bitmapPool, Bitmap original, int width, int height) { Bitmap result = (width, height, _8888); // If no matching Bitmap is in the pool, get will return null, so we should //allocate. if (result == null) { // Use ARGB_8888 since we're going to add alpha to the image. result = Bitmap(width, height, _8888); } // Create a Canvas backed by the result Bitmap. Canvas canvas = new Canvas(result); Paint paint = new Paint(); ha(128); // Draw the original Bitmap onto the result Bitmap with a transformation. tmap(original, 0, 0, paint); // Since we've replaced our original Bitmap, we return our new Bitmap here. Glide will // will take care of returning our original Bitmap to the BitmapPool for us.
return result;}
发布评论