【Android】Glide的简单使用(下)

文章目录

      • 缓存设置
      • 内存缓存
      • 硬盘缓存
      • 自定义磁盘缓存行为
      • 图片请求优先级
      • 缩略图
      • 旋转图片
      • `Glide`的回调:`Targets`
          • `BaseTarget`
          • `Target`注意事项
          • 设置具体尺寸的`Target`
      • 调试及`Debug`
          • 获取异常信息
      • 配置第三方网络库
      • 自定义缓存

缓存设置

java 复制代码
GlideApp  
    .with(context)
    .load(gifUrl)
    .asGif()
    .error(R.drawable.full_cake)
    .diskCacheStrategy(DiskCacheStrategy.DATA)
    .into(imageViewGif);

内存缓存

默认情况下不用去操作缓存设置,因为Glide默认会使用内存和硬盘缓存(所以有时候第二次加载会很快),但是如果在知道某一个图片会快速变化时,可以关闭缓存功能。

java 复制代码
GlideApp  
    .with(context)
      .load(Images[0])
      .skipMemoryCache(true) 
      .into(imageView);

上面调用了.skipMemoryCache(true)方法来告诉Glide禁用内存缓存功能。这就意味着Glide不会将图片缓存到内存中,但是这只是影响内存缓存,Glide仍然会将图片缓存到硬盘中来避免下一次显示该图片时重复请求。

硬盘缓存

如上面所讲到的,即使你关闭了内存缓存,所请求的图片仍然会被保存在设备的磁盘存储上。如果你有一张不段变化的图片,但是都是用的同一个URL,你可能需要禁止磁盘缓存了。

可以用.diskCacheStrategy()方法改变Glide的行为。不同于.skipMemoryCache()方法,它将需要从枚举型变量中选择一个,而不是一个简单的boolean。如果你想要禁止请求的磁盘缓存,使用枚举型变量DiskCacheStrategy.NONE作为参数。

java 复制代码
GlideApp  
    .with(context)
      .load(Images[1])
      .diskCacheStrategy(DiskCacheStrategy.NONE)
      .into(imageView);

上面的这种方式只是会禁用硬盘缓存,Glide还会使用内存缓存。

如果想把内存缓存和硬盘缓存都禁用,需要同时设置上面的两个方法

java 复制代码
GlideApp  
    .with(context)
      .load(Images[1])
      .diskCacheStrategy(DiskCacheStrategy.NONE)
      .skipMemoryCache(true)
      .into(imageView);

自定义磁盘缓存行为

如从上面提到的,Glide为硬盘缓存提供了多种设置方式。Glide的磁盘缓存是相当复杂的。例如,Picasso只缓存全尺寸图片。Glide,会缓存原始,全尺寸的图片和额外的小版本图片。例如,如果你请求一个1000x1000像素的图片,你的ImageView500x500像素,Glide会保存两个版本的图片到缓存里。

  • DiskCacheStrategy.NONE禁用硬盘缓存功能

  • DiskCacheStrategy.DATA只缓存原始的全尺寸图. 例如上面例子中1000x1000像素的图片

  • DiskCacheStrategy.RESOURCE只缓存最终剪辑转换后降低分辨的图片。例如上面离职中500x500像素的图片

  • DiskCacheStrategy.AUTOMATIC基于资源只能选择缓存策略(默认的行为)

  • DiskCacheStrategy.ALL缓存所有分辨率对应的类型的图片

图片请求优先级

Glide支持使用.priority()方法来设置图片请求的优先级,优先级高的会优先进行加载。

  • Priority.LOW

  • Priority.NORMAL

  • Priority.HIGH

  • Priority.IMMEDIATE

java 复制代码
    GlideApp
        .with(context)
        .load(image)
        .priority(Priority.HIGH)
        .into(imageView1);
    GlideApp
        .with(context)
        .loadimage)
        .priority(Priority.LOW)
        .into(imageView2);

    GlideApp
        .with(context)
        .load(image)
        .priority(Priority.LOW)
        .into(imageView3);

缩略图

缩略图不同于占位图。

占位图应当是跟app绑定在一起的资源(App本地资源drawable/Bitmap)。

缩略图是一个动态的占位图,可以从网络加载。缩略图也会被先加载,直到实际图片请求加载完毕。如果因为某些原因,缩略图获得的时间晚于原始图片,它并不会替代原始图片,而是简单地被忽略掉。

  • .thumbnail()能够让小的缩略 图平滑过渡到一个高分辨率的大图(参数为浮点乘法运算)
java 复制代码
String imageUrl = "xxx";

GlideApp  
    .with(context)
    .load(imageUrl)
    .thumbnail(0.1f)
    .into(imageView);

例如,如果你传递一个0.1f作为参数,Glide会加载原始图片大小的10%的图片。如果原始图片有1000x1000像素,缩略图的分辨率为100x100像素。

.thumbnail()传入一个浮点类型的参数,有时不会起效。因为如果缩略图的生成也需要从网络加载同样全分辨率图片后才可以,那这样加载速度并不会比不用缩略图快。

  • 因此Glide提供了另一个方法去加载和显示缩略图。第二种方式需要传递一个新的Glide请求作为参数。
java 复制代码
// setup Glide request without the into() method
RequestBuilder<Drawable> thumbnailRequest = GlideApp  
    .with(context)
    .load(imageUrl);

// pass the request as a a parameter to the thumbnail request
GlideApp  
    .with(context)
      .load(imageUrl)
      .thumbnail(thumbnailRequest)
      .into(imageView);

区别在于第一个缩略图请求是完全独立于第二个原始请求的。缩略图可以来自不同资源或者图片URL,你可以在它上面应用不同的变换。

旋转图片

android.graphics.Matrix中,能够旋转Bitmap图片

java 复制代码
Bitmap bitmap = ... // Bitmap的路径

Matrix matrix = new Matrix();  
matrix.postRotate(rotateRotationAngle);

Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);  

但是如果要在Glide中使用旋转方法,需要用BitmapTransformation()进行包裹,我们需要自定义一个类继承BitmapTransformation,//说明我们也可以实现不同的旋转方式。

java 复制代码
public class RotateTransformation extends BitmapTransformation {

    private float rotateRotationAngle = 0f;

    public RotateTransformation(Context context, float rotateRotationAngle) {
        super( context );

        this.rotateRotationAngle = rotateRotationAngle;
    }

    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        Matrix matrix = new Matrix();

        matrix.postRotate(rotateRotationAngle);

        return Bitmap.createBitmap(toTransform, 0, 0, toTransform.getWidth(), toTransform.getHeight(), matrix, true);
    }

    @Override
    public String getId() {
        return "rotate" + rotateRotationAngle;
    }
}

然后将上面的方法传递到.transform()中:

java 复制代码
private void loadImageOriginal() {  
    Glide
        .with( context )
        .load( eatFoodyImages[0] )
        .into( imageView1 );
}

private void loadImageRotated() {  
    Glide
        .with( context )
        .load( eatFoodyImages[0] )
        .transform( new RotateTransformation( context, 90f ))
        .into( imageView3 );
}

Glide的回调:Targets

假设我们不想将加载的图片显示到ImageView上,而是只想得到对应的BitmapGlide提供了一种可以通过Targets获取Bitmap的方法。 Targetcallback没什么不同,都是在通过Glide的异步线程下载和处理后返回结果。

Glide提供了多个不同目的的targets,我们先从BaseTarget开始。

BaseTarget
java 复制代码
private BaseTarget target = new BaseTarget<BitmapDrawable>() {  
  @Override
  public void onResourceReady(BitmapDrawable bitmap, Transition<? super BitmapDrawable> transition) {
    // do something with the bitmap
    // for demonstration purposes, let's set it to an imageview
    imageView1.setImageDrawable(bitmap);
  }
  
  
  @Override
  public void getSize(SizeReadyCallback cb) {
    cb.onSizeReady(SIZE_ORIGINAL, SIZE_ORIGINAL);
  }
  
  
  @Override
  public void removeCallback(SizeReadyCallback cb) {}
};



private void loadImageSimpleTarget() {  
  GlideApp
    .with(context) // could be an issue!
    .load(Images[0])
    .into(target);
}

需要重写getSize方法,并且调用cb.onSizeReady(SIZE_ORIGINAL, SIZE_ORIGINAL);来保证Glide使用最高质量的值。当然,也可以传递一个具体的值,例如 根据View的大小返回。

Target注意事项

除了Target的回调系统,还需要注意:

  • 第一个是BaseTarget对象的定义。Java/Android可以允许在.into()内匿名定义,但这会显著增加在Glide处理完图片请求前Android垃圾回收清理匿名target对象的可能性。最终,会导致图片被加载了,但是回调永远不会被调用。所以,请确保将你的回调定义为一个字段对象,防止被万恶的Android垃圾回收给清理掉。

  • 第二个关键部分是Glide.with(context)。这个问题实际上是Glide一个特性(监听绑定活动):当你传递了一个context,例如当前appactivity,当activity停止后,Glide会自动停止当前的请求。这种整合到app生命周期内是非常有用的,但也是很难处理的。如果你的target是独立于app的生命周期。这里的解决方案是使用application的contextapp自己停止运行的时候,Glide会只取消掉图片的请求。

java 复制代码
private void loadImageSimpleTargetApplicationContext() {  
    GlideApp
        .with(context.getApplicationContext() ) // safer!
        .load(Images[1]) 
        .asBitmap()
        .into(target2);
}
设置具体尺寸的Target

通过Target的另一个问题就是它没有具体的尺寸。如果在.into()方法的参数中传递一个ImageView,Glide会根据ImageView的大小来控制图片的尺寸。例如在加载一个1000x1000的 图片时,但是要显示到的ImageView的大小是250x250Glide会把该图片裁剪到小的尺寸来节省处理时间和内存。显示,在使用Targets时,这种方式并没有效果,因为根本不知道所需要的图片的大小。但是,如果你知道图片的最终所需要的尺寸时,你可以在callback中指定图片的尺寸来节省内存。

java 复制代码
private BaseTarget target2 = new BaseTarget<BitmapDrawable>() {  
  @Override
  public void onResourceReady(BitmapDrawable bitmap, Transition<? super BitmapDrawable> transition) {
    // do something with the bitmap
    // for demonstration purposes, let's set it to an imageview
    imageView2.setImageDrawable(bitmap);
  }

  @Override
  public void getSize(SizeReadyCallback cb) {
    cb.onSizeReady(250, 250);
  }

  @Override
  public void removeCallback(SizeReadyCallback cb) {}
};

private void loadImageSimpleTargetApplicationContext() {  
  GlideApp
    .with(context.getApplicationContext()) // safer!
    .load(eatFoodyImages[1])
    .into(target2);
}

通过cb.onSizeReady(250, 250);来指定尺寸。

因为该View并没有继承ImageView所以不能直接使用.into()方法。我们可以创建一个ViewTarget来替代.into()方法进行使用:

java 复制代码
FutureStudioView customView = (FutureStudioView) findViewById( R.id.custom_view );
​
viewTarget = new ViewTarget<FutureStudioView, BitmapDrawable>(customView) {  
  @Override
  public void onResourceReady(BitmapDrawable bitmap, Transition<? super BitmapDrawable> transition) {
    this.view.setImage(bitmap);
  }
};
​
GlideApp  
    .with(context.getApplicationContext()) // safer!
    .load(eatFoodyImages[2])
    .into(viewTarget);

调试及Debug

可以通过adb命令来开启Glide的调试log adb shell setprop log.tag.GenericRequest DEBUG

获取异常信息

Glide不能直接通过GenericRequest类获取日志,但是我们可以获取异常信息。例如,当一个图片获取不到时,glide会抛出一个异常并且显示.error() 方法设置的错误图片。如果想明确哪里出了异常,可以通过.listener()方法传递一个listener对象进去。

首先,创建一个listener对象作为一个成员变量,避免被垃圾回收:

java 复制代码
private RequestListener<Bitmap> requestListener = new RequestListener<Bitmap>() {  
  @Override
  public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
    // todo log exception to central service or something like that

    // important to return false so the error placeholder can be placed
    return false;
  }

  @Override
  public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
    // everything worked out, so probably nothing to do
    return false;
  }
};

GlideApp  
    .with(context)
    .asBitmap()
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .listener(requestListener)
    .error(R.drawable.cupcake)
    .into(imageViewPlaceholder);

配置第三方网络库

  • OkHttp
java 复制代码
// image loading library Glide
compile 'com.github.bumptech.glide:glide:4.1.1'  
annotationProcessor 'com.github.bumptech.glide:compiler:4.1.1'

// Glide's OkHttp2 Integration 
compile 'com.github.bumptech.glide:okhttp-integration:4.1.1@aar'  
compile 'com.squareup.okhttp:okhttp:2.7.5'  
  • Volley没学。。
java 复制代码
// image loading library Glide
compile 'com.github.bumptech.glide:glide:4.1.1'  
annotationProcessor 'com.github.bumptech.glide:compiler:4.1.1'
​
// Glide's Volley Integration 
compile 'com.github.bumptech.glide:volley-integration:4.1.1@aar'  
compile 'com.android.volley:volley:1.0.0'  
  • OkHttp3
java 复制代码
// image loading library Glide
compile 'com.github.bumptech.glide:glide:4.1.1'  
annotationProcessor 'com.github.bumptech.glide:compiler:4.1.1'
​
// Glide's OkHttp3 Integration 
compile 'com.github.bumptech.glide:okhttp3-integration:4.1.1@aar'  
compile 'com.squareup.okhttp3:okhttp:3.8.1'  

自定义缓存

不会。。。。

相关推荐
lifallen几秒前
Paimon vs. HBase:全链路开销对比
java·大数据·数据结构·数据库·算法·flink·hbase
深栈解码40 分钟前
JMM深度解析(三) volatile实现机制详解
java·后端
liujing102329291 小时前
Day04_刷题niuke20250703
java·开发语言·算法
whysqwhw1 小时前
OkHttp深度架构缺陷分析与演进规划
android
Brookty1 小时前
【MySQL】JDBC编程
java·数据库·后端·学习·mysql·jdbc
用户7093722538511 小时前
Android14 SystemUI NotificationShadeWindowView 加载显示过程
android
能工智人小辰1 小时前
二刷 苍穹外卖day10(含bug修改)
java·开发语言
DKPT1 小时前
Java设计模式之结构型模式(外观模式)介绍与说明
java·开发语言·笔记·学习·设计模式
缘来是庄1 小时前
设计模式之外观模式
java·设计模式·外观模式
木叶丸2 小时前
跨平台方案该如何选择?
android·前端·ios