基础
基础用法
Glide.with(this)
.load(url) //资源地址 本地uri,网络资源,图片路径
.asGif() // 指定资源样式 还可以asBitmap(),但是glide会自动判断,非特殊情况不用指定
.placeholder(R.drawable.loading) //加载过程显示
.error(R.drawable.error) // 加载错误显示
.diskCacheStrategy(DiskCacheStrategy.NONE) //缓存设置
.centerCrop() // 图片剪切样式
.priority(Priority.HIGH) //加载优先级
.thumbnail(0.2f) //缩略图,显示较小图片时用
.override(100, 100) //指定图片大小,这样可以节省内存消耗
.into(imageView);
清理缓存
Glide.get(context).clearDiskCache();//清理磁盘缓存 需要在子线程中执行
Glide.get(context).clearMemory();//清理内存缓存 可以在UI主线程中进行
停止/重启请求
Glide.with(context).resumeRequests();
Glide.with(context).resumeRequestsRecursive();
Glide.with(context).pauseRequests();
Glide.with(context).pauseAllRequests();
基处知识
内存使用量计算
ARGB_8888 :32位图,带透明度,每个像素占4个字节
ARGB_4444 :16位图,带透明度,每个像素占2个字节
RGB_565 :16位图,不带透明度,每个像素占2个字节
ALPHA_8 :32位图,只有透明度,不带颜色,每个像素占4个字节
glide 默认使用RGB_565加载 一张4000 * 2000图片
4000 * 2000 * 2(Byte) / 1024 / 1024 = 15 (MB)
缓存
Glide不仅仅缓存文件,还会缓存与缓存文件相关的内容,如图片大小,使用时应用的变化和设置等等
选项
Requestions
RequestOptions cropOptions = new RequestOptions().centerCrop(context);
...
Glide.with(fragment)
.load(url)
.apply(cropOptions)
.into(imageView);
apply()
方法可以被调用多次,因此RequestOption
可以被组合使用- 如果
RequestOptions
对象之间存在相互冲突的设置,那么只有最后一个被应用的RequestOptions
会生效。
bitmapTransform 把bitmap转变为各种样式
Glide.with(context)
.load(headUrl + url)
.apply(RequestOptions.bitmapTransform(new CircleCrop()))
.into(imageView);
TransitionOptions
使用场景
- view淡入
- 占位符交叉淡入
import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade;
Glide.with(fragment)
.load(url)
.transition(withCrossFade())
.into(view);
使用动画效果
ViewPropertyAnimation.Animator animationObject = new ViewPropertyAnimation.Animator() {
@Override
public void animate(View view) {
// if it's a custom view class, cast it here
// then find subviews and do the animations
// here, we just use the entire view for the fade animation
view.setAlpha( 0f );
ObjectAnimator fadeAnim = ObjectAnimator.ofFloat( view, "alpha", 0f, 1f );
fadeAnim.setDuration( 2500 );
fadeAnim.start();
}
};
GlideApp
.with(context)
.load(eatFoodyImages[1])
.transition(GenericTransitionOptions.with(animationObject))
// .transition(GenericTransitionOptions.with(R.anim.zoom_in)) 支持xml形式
.into(imageView2);
RequestBuilder
- 你想加载的资源类型(Bitmap, Drawable, 或其他)
- 你要加载的资源地址(url/model)
- 你想最终加载到的View
- 任何你想应用的(一个或多个)
RequestOption
对象 - 任何你想应用的(一个或多个)
TransitionOption
对象 - 任何你想加载的缩略图
thumbnail()
//构造
RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).asDrawable();
RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).load(url);
//as.. 选择资源类型
RequestBuilder<Bitmap> requestBuilder = Glide.with(fragment).asBitmap();
//requestOptions transition
RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).asDrawable();
requestBuilder.apply(requestOptions);
requestBuilder.transition(transitionOptions);
//复用
RequestBuilder<Drawable> requestBuilder =
Glide.with(fragment)
.asDrawable()
.apply(requestOptions);
for (int i = 0; i < numViews; i++) {
ImageView view = viewGroup.getChildAt(i);
String url = urls.get(i);
requestBuilder.load(url).into(view);
}
缩略图 (Thumbnail) 请求
优先加载本地低分辨率图,在加载无损版本
Glide.with(fragment)
.load(url)
.thumbnail(
//.override 设置本地版本加载大小
Glide.with(fragment).load(thumbnailUrl)
)
.into(imageView);
在失败时开始新的请求
Glide.with(fragment)
.load(primaryUrl)
.error(Glide.with(fragment)
.load(fallbackUrl))
.into(imageView);
组件选项
Option
类是给Glide的组件添加参数的通用办法,包括ModelLoaders
,ResourceDecoders
,ResourceEncoders
,Encoders
等等
用法设置请求超时时间
Glide.with(context)
.load(url)
.option(MyCustomModelLoader.TIMEOUT_MS, 1000L)
.into(imageView);
RequestOptions options = new RequestOptions()
.set(MyCustomModelLoader.TIMEOUT_MS, 1000L);
Glide.with(context)
.load(url)
.apply(options)
.into(imageView);
Transformations
内置类型
Glide.with(fragment)
.load(url)
.fitCenter()
.into(imageView);
RequestOptions options = new RequestOptions();
options.centerCrop();
Glide.with(fragment)
.load(url)
.apply(options)
.into(imageView);
多重变换
Glide.with(fragment)
.load(url)
// .transform(new FitCenter(), new YourCustomTransformation())
.transform(new MultiTransformation(new FitCenter(), new YourCustomTransformation())
.into(imageView);
【注意】: 传入变换参数的顺序,决定了这些变换的应用顺序
定制变换
CircleCrop.java
public class CircleCrop extends BitmapTransformation {
// The version of this transformation, incremented to correct an error in a previous version.
// See #455.
private static final int VERSION = 1;
private static final String ID = "com.bumptech.glide.load.resource.bitmap.CircleCrop." + VERSION;
private static final byte[] ID_BYTES = ID.getBytes(CHARSET);
// Bitmap doesn't implement equals, so == and .equals are equivalent here.
@SuppressWarnings("PMD.CompareObjectsWithEquals")
@Override
protected Bitmap transform(
@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
return TransformationUtils.circleCrop(pool, toTransform, outWidth, outHeight);
}
@Override
public boolean equals(Object o) {
return o instanceof CircleCrop;
}
@Override
public int hashCode() {
return ID.hashCode();
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
messageDigest.update(ID_BYTES);
}
}
使用
Glide.with(context)
.load(headUrl + url)
.apply(RequestOptions.bitmapTransform(new CircleCrop()))
.into(imageView);
Target
常用的实现类 ViewTarget、
ImageViewTargets
、DrawableImageViewTarget
Target<Drawable> target =
Glide.with(context)
.load(url)
.into(new Target<Drawable>() {
@Override public void onStart() {
}
@Override public void onStop() {
}
@Override public void onDestroy() {
}
@Override public void onLoadStarted(@Nullable Drawable placeholder) {
}
@Override public void onLoadFailed(@Nullable Drawable errorDrawable) {
}
@Override public void onResourceReady(@NonNull Drawable resource,
@Nullable Transition<? super Drawable> transition) {
}
@Override public void onLoadCleared(@Nullable Drawable placeholder) {
}
@Override public void getSize(@NonNull SizeReadyCallback cb) {
}
@Override public void removeCallback(@NonNull SizeReadyCallback cb) {
}
@Override public void setRequest(@Nullable Request request) {
}
@Nullable @Override public Request getRequest() {
return null;
}
});
取消和重用
- Glide.with(fragment).clear(target); 返回的
Target
来clear()
之前的加载,这将在不需要开始新的加载的情况下释放掉任何相关资源: - 仅对ViewTarget而言,你可以在每次加载或清理调用时都传入一个新的实例,而 Glide 仍然可以从 View 的 tag 中取回之前一次加载的信息,从而达到复用的效果
Glide.with(fragment)
.load(url)
.into(new DrawableImageViewTarget(imageView));
// Some time in the future:
Glide.with(fragment)
.load(newUrl)
.into(new DrawableImageViewTarget(imageView));
尺寸 (Sizes and dimensions)
默认情况下,Glide 使用目标通过
getSize
方法提供的尺寸来作为请求的目标尺寸。这允许 Glide 选取合适的 URL,下采样,裁剪和变换合适的图片以减少内存占用,并确保加载尽可能快地完成。
ViewTarget
通过检查 View 的属性和/或使用一个OnPreDrawListener
在 View 绘制之前直接测量尺寸来实现getSize()
方法。因此, Glide 可以自动调整大部分图片以匹配目标View
请参考 ViewTarget
中的逻辑。
动画资源和定制目标
Glide.with(fragment)
.asGif()
.load(url)
.into(new SimpleTarget<>() {
@Override
public void onResourceReady(GifDrawable resource, Transition<GifDrawable> transition) {
//gif
if (resource instanceof Animatable) {
resource.start();
}
}
});
过渡
允许你定义 Glide 如何从占位符到新加载的图片,或从缩略图到全尺寸图像过渡。
- 4.x 默认不会使用交叉淡入动画
- 过渡动画效果在安卓中消耗 比较大需要谨慎使用
定制过渡
配置
AppGlideModule
全局唯一,多个冲突LibraryGlideModule
可添加多个
基本用法
加入依赖
compile 'com.github.bumptech.glide:annotations:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
混淆
-keep public class extends com.bumptech.glide.module.AppGlideModule
-keep class com.bumptech.glide.GeneratedAppGlideModuleImpl
在 Glide 的 Flickr 示例应用 中
@GlideModule
public class FlickrGlideModule extends AppGlideModule {
@Override
public void registerComponents(Context context, Registry registry) {
// Photo.class 是一个普通的bean
registry.append(Photo.class, InputStream.class, new FlickrModelLoader.Factory());
}
}
@GlideModule
public final class OkHttpLibraryGlideModule extends LibraryGlideModule {
@Override
public void registerComponents(Context context, Glide glide, Registry registry) {
registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory());
}
}
应用程序选项
GlideBuilder 属性
- .setMemoryCache(MemoryCache memoryCache)
- .setBitmapPool(BitmapPool bitmapPool)
- .setDiskCache(DiskCache.Factory diskCacheFactory)
- .setDiskCacheService(ExecutorService service)
- .setResizeService(ExecutorService service)
- .setDecodeFormat(DecodeFormat decodeFormat)
@GlideModule
public class YourAppGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
//自定义 MemoryCache 的大小
MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context)
.setMemoryCacheScreens(2)
.build();
builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize()));
//直接覆写缓存大小
int memoryCacheSizeBytes = 1024 * 1024 * 20; // 20mb
builder.setMemoryCache(new LruResourceCache(memoryCacheSizeBytes));
}
}
Bitmap 池
YourAppGlideModule{
MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context)
.setBitmapPoolScreens(3)
.build();
builder.setBitmapPool(new LruBitmapPool(calculator.getBitmapPoolSize()));
int bitmapPoolSizeBytes = 1024 * 1024 * 30; // 30mb
builder.setBitmapPool(new LruBitmapPool(bitmapPoolSizeBytes));
}
磁盘缓存 默认磁盘大小为 250 MB
//存位置改到外部存储
builder.setDiskCache(new ExternalCacheDiskCacheFactory(context));
//改变磁盘缓存的大小:
int diskCacheSizeBytes = 1024 1024 100; 100 MB
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, diskCacheSizeBytes));
默认请求选项
- 全局生效
- 会覆盖之前设置
方式一, APPGlideModule设置方式
@GlideModule
public class YourAppGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setDefaultRequestOptions(
new RequestOptions()
.format(DecodeFormat.RGB_565)
.disallowHardwareBitmaps());
}
}
方式二. RequestOptions
Glide.with(fragment)
.applyDefaultRequestOptions(
new RequestOptions()
.format(DecodeFormat.RGB_565)
.disallowHardwareBitmaps());
注册组件
ModelLoader
, 用于加载自定义的 Model(Url, Uri,任意的 POJO )和 Data(InputStreams, FileDescriptors)。ResourceDecoder
, 用于对新的 Resources(Drawables, Bitmaps)或新的 Data 类型(InputStreams, FileDescriptors)进行解码。Encoder
, 用于向 Glide 的磁盘缓存写 Data (InputStreams, FileDesciptors)。ResourceTranscoder
,用于在不同的资源类型之间做转换,例如,从 BitmapResource 转换为 DrawableResource 。ResourceEncoder
,用于向 Glide 的磁盘缓存写 Resources(BitmapResource, DrawableResource)。
@GlideModule
public class YourAppGlideModule extends AppGlideModule {
@Override
public void registerComponents(Context context, Registry registry) {
//prepend
//replace
registry.append(Photo.class, InputStream.class, new CustomModelLoader.Factory());
}
}
案例:ModelLoader
和 ResourceDecoder
实践案例
- 提高glide图片加载质量
Android 中有两个主要的方法对图片进行解码:ARGB8888 和 RGB565。前者为每个像素使用了 4 个字节,后者仅为每个像素使用了 2 个字节。ARGB8888 的优势是图像质量更高以及能存储一个 alpha 通道。Glide 默认使用低质量的 RGB565
public class SimpleGlideModule implements GlideModule {
@Override public void applyOptions(Context context, GlideBuilder builder) {
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
}
@Override public void registerComponents(Context context, Glide glide) {
// nothing to do here
}
}
其他配置
未捕获异常策略
@GlideModule
public class YourAppGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
final UncaughtThrowableStrategy myUncaughtThrowableStrategy = new ...
builder.setDiskCacheExecutor(newDiskCacheExecutor(myUncaughtThrowableStrategy));
builder.setResizeExecutor(newSourceExecutor(myUncaughtThrowableStrategy));
}
}
日志级别
@GlideModule
public class YourAppGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setLogLevel(Log.DEBUG);
}
}
缓存
缓存四个级别
Active Resources(View 正在显示) > Memory cache(加载过并在内存) > Resource(解密并存在磁盘) > Data (曾经写入过文件)
配置缓存
Glide.with(fragment)
.load(url)
//.onlyRetrieveFromCache(true)
//.skipMemoryCache(true)
//.diskCacheStrategy(DiskCacheStrategy.NONE)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(imageView);
定制缓存刷新Key值
文件 ObjectKey
Glide.with(yourFragment)
.load(yourFileDataModel)
.signature(new ObjectKey(yourVersionMetadata/*修改日期*/))
.into(yourImageView);
媒体存储签名MediaStore
Glide.with(fragment)
.load(mediaStoreUri)
.signature(new MediaStoreSignature(mimeType, dateModified, orientation))
.into(view);
定义你自己的签名
public class IntegerVersionSignature implements Key {
private int currentVersion;
public IntegerVersionSignature(int currentVersion) {
this.currentVersion = currentVersion;
}
@Override
public boolean equals(Object o) {
if (o instanceof IntegerVersionSignature) {
IntegerVersionSignature other = (IntegerVersionSignature) o;
return currentVersion == other.currentVersion;
}
return false;
}
@Override
public int hashCode() {
return currentVersion;
}
@Override
public void updateDiskCacheKey(MessageDigest md) {
messageDigest.update(ByteBuffer.allocate(Integer.SIZE).putInt(signature).array());
}
}
组件
常用的组件概述
-
A factory interface for translating an arbitrarily complex data model into a
concrete data type that can be used by an
DataFetcher
to obtain the data for a resource represented by the model. -
T
- The type the resource will be decoded from (File, InputStream etc).Z
- The type of the decoded resource (Bitmap, Drawable etc). -
T
- The type of the data contained by the resource.
案例
1. 加载加载角图片度
开源库
2. 下载文件/获取缓存文件路径
FutureTarget<File> target = Glide.with(context).load(url).downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
final File imageFile = target.get();
3. 根据加载的资源动态设置ImageView大小
主要是RequestListener 的应用, 获取资源的数据resource.getIntrinsicHeight()
/**
* 自适应宽度加载图片。保持图片的长宽比例不变,通过修改imageView的高度来完全显示图片。
*/
public static void loadIntoUseFitWidth(Context context, final String imageUrl, int errorImageId, final ImageView imageView) {
Glide.with(context)
.load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.listener(new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
if (imageView == null) {
return false;
}
if (imageView.getScaleType() != ImageView.ScaleType.FIT_XY) {
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
}
ViewGroup.LayoutParams params = imageView.getLayoutParams();
int vw = imageView.getWidth() - imageView.getPaddingLeft() - imageView.getPaddingRight();
float scale = (float) vw / (float) resource.getIntrinsicWidth();
int vh = Math.round(resource.getIntrinsicHeight() * scale);
params.height = vh + imageView.getPaddingTop() + imageView.getPaddingBottom();
imageView.setLayoutParams(params);
return false;
}
})
.placeholder(errorImageId)
.error(errorImageId)
.into(imageView);
}
4. 【官方】编写定制的 ModelLoader
相关开源库
- BigImageViewPager 基于glide的大图预览库
参考
- glide github官网
- Glide 官网中文文档 【重点.科学上网】
- Glide最全解析(郭霖的glide系列) (以Glide3.7.0源码为例 共8篇 第2篇较难懂 如果不太理解可以跳过直接从第3篇 缓存开始读 )
- Android面试题:Glide
- Glide 3.6.1 系列预览