Glide用法
Glide 用法
Glide 加载本地图片资源&网络图片
网络图
1
2
3
4
5
ImageView imageView = findViewById(R.id.image_view);
String url = "https://www.niwoxuexi.com/statics/images/nougat_bg.png";
Glide.with(context)
.load(url)
.into(imageView);
本地图
加载 SD 卡资源图片
1
2
3
4
5
6
7
8
9
10
11
12
// 加载SD卡根目录的test.jpg 图片
String path = "file://"+ Environment.getExternalStorageDirectory().getPath()+"/test.jpg";
Glide.with(context)
.load(path)
.into(imageView);
或者
ImageView imageView = findViewById(R.id.image_view);
// 加载SD卡根目录的test.jpg 图片 ,通过Flie文件读取
File file = new File(Environment.getExternalStorageDirectory(), "test.jpg");
Glide.with(context)
.load(file)
.into(imageView);
加载 drawable 资源图片
1
2
3
4
5
ImageView imageView = findViewById(R.id.image_view);
// 加载资源文件 drawable 下的图片 image_test.png
Glide.with(this)
.load(R.drawable.iamge_test)
.into(imageView);
加载 assets 资源文件
1
2
3
4
5
6
ImageView imageView = findViewById(R.id.image_view);
// 加载资源文件 assets 下的图片 image_test.png
String path = "file:///android_asset/image_test.png";
Glide.with(this)
.load(path)
.into(imageView);
加载 raw 资源图片
方法:load(“android.resource://包名/raw/raw_1”) 或 load(“android.resource://包名/raw/”+R.raw.raw_1)
Glide 还可以加载的类型
Glide Transformation 转换
glide wiki: https://github.com/bumptech/glide/wiki/Transformations
介绍
glide 包括 2 种默认的 transformations
,fitCenter
和 centerCrop
,其他类型的可参考 glide-transformations
- FitCenter
缩放图片会保持图片原有的宽高比,能完整填充给定的宽和高;采用最小的 scale(缩放倍数大的) 来缩放图片,所以一边是完整匹配给定的宽高,一边是小于或者等于给定的宽高。(即缩放的图片会完整的显示到给定控件的宽高,有一边是等于或者小于另外一边控件的宽高)
等同于 Android 系统 ImageView 的 ScaleType.FIT_CENTER - CenterCrop
等同于 Android 的 ImageView 中的ScaleType.CENTER_CROP
自定义[transformations](https://github.com/bumptech/glide/wiki/Transformations#custom-transformations)
- 简单的方式是直接继承
BitmapTransformation
Sizing
Glide 会自动根据传递进来的 View 的 layout_wight
,match_parent
或者具体的宽高值来确定图片的大小。
如果你想指定一个自定义的尺寸,用 .override(int,int)
方法。或者你想在自定义 View 上加载图片,使用自定义的 Custom Targets。
Bitmap re-use
为了减少 GC 操作,用 BitmapPool
来释放和重复利用已经存在的 Bitmap。遵守以下几点:
- 在
transform()
方法中不要回收 Bitmap,glide 会自动帮我们做这些。 - 如果你拿超过一个 Bitmap 或者不再使用一个 Bitmap 从
Bitmap
拿到的,返回额外的给BitmapPool
- 如果你的
transformaions
没有替换原始的 bitmap,返回这个 Bitmap 在transform()
方法。
使用
.transform()
使用任何转换,无论它是图像还是 gif.bitmapTransformation()
它只能用于 bitmap 转换- 多种转换
如何同时调用了.transform()
或.bitmapTransform()
,之前的配置就会被覆盖掉的。如果你还是可以运用多种转换的,通过传递多个转换对象作为参数传给.transform()
或.bitmapTransform()
。
1
2
3
4
5
Glide
.with( context )
.load( eatFoodyImages[1] )
.transform( new GreyscaleTransformation( context ), new BlurTransformation( context ) )
.into( imageView2 );
提示: 当你用了转换后你就不能使用 .centerCrop()
或 .fitCenter()
了。_
开源库 glide-transformations
这个库有两个不同的版本。扩展版本包含了更多的转换,它是通过设备的 GPU 来计算处理的。这个版本需要有额外的依赖,所以这两个版本的设置有一点不同。你应该看看所拥有的转换方法的列表,再去决定你需要使用哪个版本。
Reference
Glide - 自定义转换
Glide Transformation 简洁和 glide-transformations 库推荐
http://mrfu.me/2016/02/28/Glide_Custom_Transformations/
How to Blur Images Efficiently with Android’s RenderScript
使用 RenderScripe 来模糊图片
https://futurestud.io/tutorials/how-to-blur-images-efficiently-with-androids-renderscript
Glide 缓存策略
注意的是:Glide 默认是开启内存缓存和磁盘缓存的
内存缓存
- 跳过内存缓存
.skipMemoryCache(true)
这样跳过了 Glide 的内存缓存,但 Glide 将会仍然利用磁盘缓存来避免重复的网络请求。
1
2
3
4
Glide.with(this)
.load(ImageUtils.getImgs()[0])
.skipMemoryCache(true)
.into(mImageView);
提示: 注意一个事实,对于相同的 URL ,如果你的初始请求没调用 .skipMemoryCache(true) 方法,你后来又调用了 .skipMemoryCache(true)
这个方法,这个资源将会在内存中获取缓存。当你想要去调整缓存行为时,确保对同一个资源调用的一致性。
磁盘缓存
- 跳过磁盘缓存
.diskCacheStrategy(DiskCacheStrategy.NONE)
内存缓存还有用
1
2
3
4
Glide.with(this)
.load(ImageUtils.getImgs()[0])
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(mImageView);
自定义磁盘缓存行为
- Picasso 仅仅缓存了全尺寸的图像。
- Glide 缓存了原始图像,全分辨率图像和另外小版本的图像。
比如,如果你请求的一个图像是 1000x1000 像素的,但你的 ImageView 是 500x500 像素的,Glide 将会把这两个尺寸都进行缓存。 .diskCacheStrategy()
方法来说不同的枚举参数的意义DiskCacheStrategy.NONE
什么都不缓存,用于跳过磁盘缓存DiskCacheStrategy.SOURCE
仅仅只缓存原来的全分辨率的图像。在我们上面的例子中,将会只有一个 1000x1000 像素的图片DiskCacheStrategy.RESULT
仅仅缓存最终的图像,即,降低分辨率后的(或者是转换后的)DiskCacheStrategy.ALL
缓存所有版本的图像(默认行为,3.6.1 以及最新的 3.7.0 .diskCacheStrategy() 默认都是DiskCacheStrategy.RESULT
?)
跳过内存缓存又跳过磁盘缓存
1
2
3
4
5
Glide.with(this)
.load(ImageUtils.getImgs()[0])
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(mImageView);
Reference
- Glide - 缓存基础
http://mrfu.me/2016/02/27/Glide_Caching_Basics/
自定义 GlideModule
applyOptions
GlideBuilder
主要有:
.setMemoryCache(MemoryCache memoryCache)
.setBitmapPool(BitmapPool bitmapPool)
.setDiskCache(DiskCache.Factory diskCacheFactory)
.setDiskCacheService(ExecutorService service)
.setResizeService(ExecutorService service)
.setDecodeFormat(DecodeFormat decodeFormat)
增加 Glide 图片质量
在 Android 的主要两个解码配置:Bitmap.Config.RGB_565
和 Bitmap.Config.ARGB_8888
。其中 ARGB_8888
存储每个像素需要 4 个字节,而 RGB_565
只使用两个字节。ARGB_8888
优势在于图像质量更高以及能存储一个 alpha 通道。Glide 默认采用的是低质量的 RGB_565,Picasso 使用的是 ARGB_8888。
1
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
自定义内存缓存和 Bitmap 缓存池大小
- 默认采用
LruResourceCache
作为内存缓存,LRU 缓存策略;大于等于 3.0 采用LruBitmapPool
作为 Bitmap 缓存池算法,小于 3.0 的 BitmapPool 实现为空。
1
2
3
4
5
6
7
8
9
10
11
12
13
MemorySizeCalculator calculator = new MemorySizeCalculator(context);
if (bitmapPool == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
int size = calculator.getBitmapPoolSize();
bitmapPool = new LruBitmapPool(size);
} else {
bitmapPool = new BitmapPoolAdapter();
}
}
if (memoryCache == null) {
memoryCache = new LruResourceCache(calculator.getMemoryCacheSize());
}
- MemorySizeCalculator
Glide 用来计算memoryCacheSize
内存缓存大小和bitmapPoolSize
Bitmap 缓存池大小
最大缓存内存计算,低内存设备单个应用可用最大内存的 0.33;不是低内存设备的 0.44
1
2
3
4
5
6
7
8
9
static final float MAX_SIZE_MULTIPLIER = 0.4f;
static final float LOW_MEMORY_MAX_SIZE_MULTIPLIER = 0.33f;
private static int getMaxSize(ActivityManager activityManager) {
final int memoryClassBytes = activityManager.getMemoryClass() * 1024 * 1024;
final boolean isLowMemoryDevice = isLowMemoryDevice(activityManager);
return Math.round(memoryClassBytes
* (isLowMemoryDevice ? LOW_MEMORY_MAX_SIZE_MULTIPLIER : MAX_SIZE_MULTIPLIER));
}
- 内存缓存大小和 Bitmap 缓存池大小
最终的内存缓存大小和 Bitmap 池缓存大小和屏幕像素密度有关
默认
bitmapPoolSize(Bitmap 缓存池大小) = 屏幕像素密度 _ 4B(ARGB_8888 占用内存字节数) _ 4(默认缓存 4 屏)
memoryCacheSize(内存缓存大小) = 屏幕像素密度 _ 4B(ARGB_8888 占用内存字节数) _ 4(默认缓存 2 屏)
如果 bitmapPoolSize + memoryCacheSize <= maxSize 就是默认值
如果大于了 maxSize,会设置为当前接近 maxSize 和值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
MemorySizeCalculator(Context context, ActivityManager activityManager, ScreenDimensions screenDimensions) {
this.context = context;
final int maxSize = getMaxSize(activityManager);
final int screenSize = screenDimensions.getWidthPixels() * screenDimensions.getHeightPixels()
* BYTES_PER_ARGB_8888_PIXEL;
int targetPoolSize = screenSize * BITMAP_POOL_TARGET_SCREENS;
int targetMemoryCacheSize = screenSize * MEMORY_CACHE_TARGET_SCREENS;
if (targetMemoryCacheSize + targetPoolSize <= maxSize) {
memoryCacheSize = targetMemoryCacheSize;
bitmapPoolSize = targetPoolSize;
} else {
int part = Math.round((float) maxSize / (BITMAP_POOL_TARGET_SCREENS + MEMORY_CACHE_TARGET_SCREENS));
memoryCacheSize = part * MEMORY_CACHE_TARGET_SCREENS;
bitmapPoolSize = part * BITMAP_POOL_TARGET_SCREENS;
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Calculated memory cache size: " + toMb(memoryCacheSize) + " pool size: " + toMb(bitmapPoolSize)
+ " memory class limited? " + (targetMemoryCacheSize + targetPoolSize > maxSize) + " max size: "
+ toMb(maxSize) + " memoryClass: " + activityManager.getMemoryClass() + " isLowMemoryDevice: "
+ isLowMemoryDevice(activityManager));
}
}
自定义磁盘缓存
Glide3.7.x 默认的磁盘缓存策略是 DiskCacheStrategy.RESULT
,默认的缓存位置为内部存储:(可以自定义先外部缓存再内部缓存空间)
1
2
3
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
- 提供了 DiskLruCacheFactory 的两个实现,
InternalCacheDiskCacheFactory
和ExternalCacheDiskCacheFactory
- InternalCacheDiskCacheFactory
应用内部缓存存储空间context.getCacheDir()
,默认是 250M 缓存空间;默认内部缓存二级目录image_manager_disk_cache
- ExternalCacheDiskCacheFactory
应用外部缓存存储空间context.getExternalCacheDir()
,默认 250M 空间;默认外部缓存二级目录image_manager_disk_cache
registerComponents
参考:
Glide - Module 实例:接受自签名证书的 HTTPS
http://mrfu.me/2016/02/28/Glide_Module_Example_Accepting_Self-Signed_HTTPS_Certificates/
Glide - Module 实例:自定义缓存
http://mrfu.me/2016/02/28/Glide_Module_Example_Customize_Caching/
Glide animated webp(webp 动画)
GlideWebpSupport
GlideWebpSupport 借助了 fresco-webp 库 的解析 来 扩展 glide 的 解码器, 实现 glide 加载 webp
- 问题
- 可以加载 webp 静态图
- 对于 webp 动态图,有的机器可以,How to use Glid load webp and animated webp?
GlideWebpDecoder
基于 libwebp,参考 Fresco 和 GlideWebpSupport 的一些实现
- 可能存在的问题(需要测试确认?)
- 掉帧?
- 用
BitmapTransformation
或库glide-transformations
需要加上
1
2
3
4
5
6
Transformation<Bitmap> circleCrop = new CircleCrop();
GlideApp.with(mContext)
.load(url)
.optionalTransform(circleCrop)
.optionalTransform(WebpDrawable.class, new WebpDrawableTransformation(circleCrop))
.into(imageView);