文章目录
-
-
- 缓存设置
- 内存缓存
- 硬盘缓存
- 自定义磁盘缓存行为
- 图片请求优先级
- 缩略图
- 旋转图片
- `Glide`的回调:`Targets`
-
-
- `BaseTarget`
- `Target`注意事项
- 设置具体尺寸的`Target`
-
- 调试及`Debug`
-
-
- 获取异常信息
-
- 配置第三方网络库
- 自定义缓存
-
缓存设置
GlideApp
.with(context)
.load(gifUrl)
.asGif()
.error(R.drawable.full_cake)
.diskCacheStrategy(DiskCacheStrategy.DATA)
.into(imageViewGif);
内存缓存
默认情况下不用去操作缓存设置,因为Glide
默认会使用内存和硬盘缓存(所以有时候第二次加载会很快),但是如果在知道某一个图片会快速变化时,可以关闭缓存功能。
GlideApp
.with(context)
.load(Images[0])
.skipMemoryCache(true)
.into(imageView);
上面调用了.skipMemoryCache(true)
方法来告诉Glide
禁用内存缓存功能。这就意味着Glide
不会将图片缓存到内存中,但是这只是影响内存缓存,Glide
仍然会将图片缓存到硬盘中来避免下一次显示该图片时重复请求。
硬盘缓存
如上面所讲到的,即使你关闭了内存缓存,所请求的图片仍然会被保存在设备的磁盘存储上。如果你有一张不段变化的图片,但是都是用的同一个URL
,你可能需要禁止磁盘缓存了。
可以用.diskCacheStrategy()
方法改变Glide
的行为。不同于.skipMemoryCache()
方法,它将需要从枚举型变量中选择一个,而不是一个简单的boolean
。如果你想要禁止请求的磁盘缓存,使用枚举型变量DiskCacheStrategy.NONE
作为参数。
GlideApp
.with(context)
.load(Images[1])
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
上面的这种方式只是会禁用硬盘缓存,Glide
还会使用内存缓存。
如果想把内存缓存和硬盘缓存都禁用,需要同时设置上面的两个方法
GlideApp
.with(context)
.load(Images[1])
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(imageView);
自定义磁盘缓存行为
如从上面提到的,Glide
为硬盘缓存提供了多种设置方式。Glide
的磁盘缓存是相当复杂的。例如,Picasso
只缓存全尺寸图片。Glide
,会缓存原始,全尺寸的图片和额外的小版本图片。例如,如果你请求一个1000x1000
像素的图片,你的ImageView
是500x500
像素,Glide
会保存两个版本的图片到缓存里。
DiskCacheStrategy.NONE
禁用硬盘缓存功能DiskCacheStrategy.DATA
只缓存原始的全尺寸图. 例如上面例子中1000x1000
像素的图片DiskCacheStrategy.RESOURCE
只缓存最终剪辑转换后降低分辨的图片。例如上面离职中500x500
像素的图片DiskCacheStrategy.AUTOMATIC
基于资源只能选择缓存策略(默认的行为)DiskCacheStrategy.ALL
缓存所有分辨率对应的类型的图片
图片请求优先级
Glide
支持使用.priority()
方法来设置图片请求的优先级,优先级高的会优先进行加载。
Priority.LOW
Priority.NORMAL
Priority.HIGH
Priority.IMMEDIATE
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()
能够让小的缩略 图平滑过渡到一个高分辨率的大图(参数为浮点乘法运算)
String imageUrl = "xxx";
GlideApp
.with(context)
.load(imageUrl)
.thumbnail(0.1f)
.into(imageView);
例如,如果你传递一个0.1f
作为参数,Glide
会加载原始图片大小的10%
的图片。如果原始图片有1000x1000
像素,缩略图的分辨率为100x100
像素。
为.thumbnail()
传入一个浮点类型的参数,有时不会起效。因为如果缩略图的生成也需要从网络加载同样全分辨率图片后才可以,那这样加载速度并不会比不用缩略图快。
- 因此
Glide
提供了另一个方法去加载和显示缩略图。第二种方式需要传递一个新的Glide
请求作为参数。
// 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图片
Bitmap bitmap = ... // Bitmap的路径
Matrix matrix = new Matrix();
matrix.postRotate(rotateRotationAngle);
Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
但是如果要在Glide
中使用旋转方法,需要用BitmapTransformation()
进行包裹,我们需要自定义一个类继承BitmapTransformation
,//说明我们也可以实现不同的旋转方式。
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()
中:
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
上,而是只想得到对应的Bitmap
。Glide
提供了一种可以通过Targets
获取Bitmap
的方法。 Target
和callback
没什么不同,都是在通过Glide
的异步线程下载和处理后返回结果。
Glide
提供了多个不同目的的targets
,我们先从BaseTarget
开始。
BaseTarget
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
,例如当前app
的activity
,当activity
停止后,Glide
会自动停止当前的请求。这种整合到app
生命周期内是非常有用的,但也是很难处理的。如果你的target
是独立于app
的生命周期。这里的解决方案是使用application的context
当app
自己停止运行的时候,Glide
会只取消掉图片的请求。
private void loadImageSimpleTargetApplicationContext() {
GlideApp
.with(context.getApplicationContext() ) // safer!
.load(Images[1])
.asBitmap()
.into(target2);
}
设置具体尺寸的Target
通过Target
的另一个问题就是它没有具体的尺寸。如果在.into()
方法的参数中传递一个ImageView
,Glide
会根据ImageView
的大小来控制图片的尺寸。例如在加载一个1000x1000
的 图片时,但是要显示到的ImageView
的大小是250x250
,Glide
会把该图片裁剪到小的尺寸来节省处理时间和内存。显示,在使用Targets
时,这种方式并没有效果,因为根本不知道所需要的图片的大小。但是,如果你知道图片的最终所需要的尺寸时,你可以在callback
中指定图片的尺寸来节省内存。
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()
方法进行使用:
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
对象作为一个成员变量,避免被垃圾回收:
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
// 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
没学。。
// 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
// 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'
自定义缓存
不会。。。。