文章

Glide用法

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 还可以加载的类型

03ym6

Glide Transformation 转换

glide wiki: https://github.com/bumptech/glide/wiki/Transformations

介绍

glide 包括 2 种默认的 transformationsfitCentercenterCrop,其他类型的可参考 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_wightmatch_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

自定义 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_565Bitmap.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 内存缓存大小和 bitmapPoolSizeBitmap 缓存池大小
    最大缓存内存计算,低内存设备单个应用可用最大内存的 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 的两个实现,InternalCacheDiskCacheFactoryExternalCacheDiskCacheFactory
  • 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

  • 问题
  1. 可以加载 webp 静态图
  2. 对于 webp 动态图,有的机器可以,How to use Glid load webp and animated webp?

GlideWebpDecoder

基于 libwebp,参考 Fresco 和 GlideWebpSupport 的一些实现

  • 可能存在的问题(需要测试确认?)
  1. 掉帧?
  • 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);
本文由作者按照 CC BY 4.0 进行授权