官方介绍
关于 Glide
Glide是一个快速高效的Android图片加载库,注重于平滑的滚动。Glide提供了易用的API,高性能、可扩展的图片解码管道(decode pipeline),以及自动的资源池技术。
Glide 支持拉取,解码和展示视频快照,图片,和GIF动画。Glide的Api是如此的灵活,开发者甚至可以插入和替换成自己喜爱的任何网络栈。默认情况下,Glide使用的是一个定制化的基于HttpUrlConnection的栈,但同时也提供了与Google Volley和Square OkHttp快速集成的工具库。
虽然Glide 的主要目标是让任何形式的图片列表的滚动尽可能地变得更快、更平滑,但实际上,Glide几乎能满足你对远程图片的拉取/缩放/显示的一切需求。
性能
Glide 充分考虑了Android图片加载性能的两个关键方面:
为了让用户拥有良好的App使用体验,图片不仅要快速加载,而且还不能因为过多的主线程I/O或频繁的垃圾回收导致页面的闪烁和抖动现象。
Glide使用了多个步骤来确保在Android上加载图片尽可能的快速和平滑:
- 自动、智能地下采样(downsampling)和缓存(caching),以最小化存储开销和解码次数;
- 积极的资源重用,例如字节数组和Bitmap,以最小化昂贵的垃圾回收和堆碎片影响;
- 深度的生命周期集成,以确保仅优先处理活跃的Fragment和Activity的请求,并有利于应用在必要时释放资源以避免在后台时被杀掉。
环境配置
Gradle依赖
implementation 'com.git`hub.bumptech.glide:glide:4.12.0'`
<dependency>
<groupId>com.github.bumptech.glide</groupId>
<artifactId>glide</artifactId>
<version>4.12.0</version>
<type>aar</type>
</dependency>
AndroidManifest.xml 中添加权限设置
<!-- 网络权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 读取权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 写入权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
基本用法
Glide 库是使用流接口(fluent interface)。对一个完整的功能请求,Glide 建造者要求最少有三个参数。
//加载图片
Glide.with(context)
.load(url)
.into(imageView);
//取消加载
Glide.with(context).clear(imageView);
context :可以传入fragment 、activity 和applicationContext 等。
load :图片资源。可以是resourceId 、url 、uri 、drawable 、file 等。
into :图片会显示到对应的 ImageView 中
取消加载并非是必要的操作,在Glide.with()中传入的context如果是activity或fragment,当它们的实例销毁时,Glide 会自动取消加载并回收资源。
private static Uri resourceIdToUri(Context context, int resourceId) {
return Uri.parse("android.resource://" + context.getPackageName()
+ "/" + resourceId);
}
占位符
Glide允许用户指定三种不同类型的占位符,分别在三种不同场景使用。他们分别是placeholder,error和falllback。
placeholder(占位符)
占位符是当请求正在执行时被展示的 Drawable 。当请求成功完成时,占位符会被请求到的资源替换。
Glide.with(context)
.load(url)
.placeholder(R.drawable.placeholder)
.into(view);
error(错误符)
error Drawable 在请求永久性失败时展示。
error()接受的参数只能是已经初始化的 drawable 对象或者指明它的资源(R.drawable.xxx)
Glide.with(context)
.load(url)
.error(R.drawable.error)
.into(view);
fallback(后备回调符)
fallback Drawable 在请求的url为 null 时展示。
Glide.with(context)
.load(url)
.fallback(R.drawable.fallback)
.into(view);
当Gilde.load()中传入的资源为null,或者是无法成功获取时,展示优先级为fallback > error > placeholder。
占位符都是独立的,可以根据开发需要来调用。除基本用法中的三个方法,Glide的其他方法也是如此。
占位符是在主线程从Android Resources加载的。占位符应当比较小且容易被系统资源缓存机制缓存起来。
提示:多个不同的View上可以使用相同的Drawable,但仅限于无状态的drawable(例如Bitmap)。但是有状态的 Drawable 不一样,在同一时间多个 View 上展示它们通常不是很安全,因为多个View会立刻修改(mutate) Drawable 。对于有状态的 Drawable ,建议传入一个资源ID,或者使用 newDrawable() 来给每个请求传入一个新的拷贝。
选项
请求选项
Glide中的大部分设置项都可以直接应用在 Glide.with() 返回的 RequestBuilder 对象上。
可用的选项包括但不限于:
如果想让应用的不同部分之间共享相同的加载选项,可以初始化一个新的 RequestOptions 对象,并在每次加载时通过 apply() 方法传入这个对象:
RequestOptions cropOptions = new RequestOptions().centerCrop(context);
Glide.with(context)
.load(url)
.apply(cropOptions)
.into(imageView);
apply() 方法可以被调用多次,因此 RequestOption 可以被组合使用。如果 RequestOptions 对象之间存在相互冲突的设置,那么只有最后一个被应用的 RequestOptions 会生效。
过渡选项
TransitionOptions 用于决定加载完成时会发生什么。
如果不使用变换,你图像将会直接出现在其显示位置,替换掉之前的图像。为了避免这种突然的改变,可以淡入view,或者让多个Drawable交叉淡入,而这些都需要使用TransitionOptions完成。
import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade;
//import com.bumptech.glide.GenericTransitionOptions.withNoTransition
Glide.with(fragment)
.load(url)
.transition(withCrossFade())
// 不发生变换
// .transition(withNoTransition())
.into(view);
不同于RequestOptions,TransitionOptions是特定资源类型独有的,假如请求加载一个 Bitmap ,需要使用 BitmapTransitionOptions ,而不是 DrawableTransitionOptions 。
RequestBuilder
- 加载的资源类型(Bitmap, Drawable, 或其他)
- 加载的资源地址(url/model)
- 最终加载到的View
- 想应用的(一个或多个)RequestOption 对象
- 想应用的(一个或多个)TransitionOption 对象
- 想加载的缩略图 thumbnail()
要构造一个 RequestBuilder 对象,可以通过先调用 Glide.with()然后再调用某一个 as 方法来完成:
RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).asDrawable();
RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).load(url);
选择资源类型
RequestBuilders 是特定于它们将要加载的资源类型的。默认情况下会得到一个 Drawable RequestBuilder ,但可以使用 as… 方法来改变请求类型。
应用 RequestOptions
前面提到,可以使用 apply() 方法应用 RequestOptions ,使用 transition() 方法应用 TransitionOptions 。
RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).asDrawable();
requestBuilder.apply(requestOptions);
requestBuilder.transition(transitionOptions);
缩略图 (Thumbnail) 请求
Glide 的 thumbnail() API 允许指定一个 RequestBuilder 以与你的主请求并行启动。
thumbnail() 会在主请求加载过程中展示。如果主请求在缩略图请求之前完成,则缩略图请求中的图像将不会被展示。thumbnail() API 允许简单快速地加载图像的低分辨率版本,并且同时加载图像的无损版本。
Glide.with(context)
.load(url)
.thumbnail(Glide.with(context).load(thumbnailUrl))
.into(imageView);
在只有url而没有thumbnailUrl的情况下,可以使用override方法。
Glide.with(context)
.load(url)
.thumbnail(Glide.with(context)
.load(url)
// .override(int width, int height)
.override(int thumbnailSize))
.into(view);
thumbnail() 方法有一个简化版本,它只需要一个 sizeMultiplier 参数
Glide.with(context)
.load(url)
.thumbnail(/*sizeMultiplier=*/ 0.1f)
.into(imageView);
在失败时开始新的请求
在 error 方法里 来指定一个 RequestBuilder,可以在主请求失败时开始一次新的加载。
Glide.with(context)
.load(primaryUrl)
.error(Glide.with(context)
.load(fallbackUrl))
.into(imageView);
如果主请求成功完成,这个error里的RequestBuilder 将不会被启动。如果你同时指定了一个 thumbnail() 和一个 error() RequestBuilder,则这个后备的 RequestBuilder 将在主请求失败时启动,即使缩略图请求成功也是如此。
请求的优先级
Priority枚举给了四个不同的选项,下面是按照递增priority(优先级)的列表:
Priority.LOW
Priority.NORMAL
Priority.HIGH
Priority.IMMEDIATE
优先级并不是完全严格遵守的。Glide 将会用他们作为一个准则,并尽可能的处理这些请求,但是它不能保证所有的图片都会按照所要求的顺序加载。
Glide.with(context)
.load(url)
.priority(Priority.HIGH)
.into(imageView);
组件选项
Option 类是给Glide的组件添加参数的通用办法,包括 ModelLoaders , ResourceDecoders , ResourceEncoders , Encoders 等等。一些Glide的内置组件提供了设置项,自定义的组件也可以添加设置项。
Option 通过 RequestOptions 类应用到请求上:
Glide.with(context)
.load(url)
.option(MyCustomModelLoader.TIMEOUT_MS, 1000L)
.into(imageView);
变换
在Glide中,Transformations 可以获取资源并修改它,然后返回被修改后的资源。通常变换操作是用来完成剪裁或对位图应用过滤器,但它也可以用于转换GIF动画,甚至自定义的资源类型。
内置类型
Glide 提供了很多内置的变换,包括:
应用
CenterCrop
CenterCrop()是一个裁剪技术,即缩放图像让它填充到 ImageView 界限内并且裁剪额外的部分。ImageView 可能会完全填充,但图像可能不会完整显示。
Glide.with(context)
.load(url)
.centerCrop()
.into(imageView)
或使用 RequestOptions
RequestOptions options = new RequestOptions();
options.centerCrop();
Glide.with(context)
.load(url)
.apply(options)
.into(imageView);
FitCenter
fitCenter() ,即缩放图像让图像都测量出来等于或小于 ImageView 的边界范围。该图像将会完全显示,但可能不会填满整个 ImageView。
Glide.with(context)
.load(url)
.fitCenter()
.into(imageView)
CircleCrop
CircleCrop()和fitCenter()行为类型,但会剪裁出圆形图片。
Glide.with(context)
.load(url)
.circleCrop()
.into(imageView)
Transformations
添加依赖
compile 'jp.wasabeef:glide-transformations:4.0.0'
//使用GPU转换
compile 'jp.co.cyberagent.android.gpuimage:gpuimage-library:xxxx'
多重变换
默认情况下,每个 transform() 调用,或任何特定转换方法的调用都会替换掉之前的变换。
如果想在单次加载中应用多个变换,请使用 MultiTransformation 类,或其快捷方法 .transforms() 。
Glide.with(context)
.load(url)
// MultiTransformation 类
// .transform(new MultiTransformation(new FitCenter(), new YourCustomTransformation())
// 快捷方法
.transform(new FitCenter(), new YourCustomTransformation())
.into(imageView);
向 MultiTransformation 的构造器传入变换参数的顺序,决定了这些变换的应用顺序。
自定义变换
一个简单的BitmapTransformation
如果只需要变换 Bitmap,最好是从继承 BitmapTransformation 开始。BitmapTransformation 为我们处理了一些基础的东西,例如,如果变换返回了一个新修改的 Bitmap ,BitmapTransformation将负责提取和回收原始的 Bitmap。
public class FillSpace extends BitmapTransformation {
private static final String ID = "com.bumptech.glide.transformations.FillSpace";
private static final String ID_BYTES = ID.getBytes(STRING_CHARSET_NAME);
@Override
public Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
if (toTransform.getWidth() == outWidth && toTransform.getHeight() == outHeight) {
return toTransform;
}
return Bitmap.createScaledBitmap(toTransform, outWidth, outHeight, /*filter=*/ true);
}
@Override
public void updateDiskCacheKey(MessageDigest messageDigest)
throws UnsupportedEncodingException {
messageDigest.update(ID_BYTES);
}
@Override
public void equals(Object o) {
return o instanceof FillSpace;
}
@Override
public int hashCode() {
return ID.hashCode();
}
}
使用这个BitmapTransformation
Glide 有两种方式去使用转换。首先是传一个类的实例作为参数给 .transform()。这里可以使用任何转换,无论它是否是用于图像还是 Gif。其他选择是使用 .bitmapTransform(),它只能用于 bitmap 的转换。因为我们上面的实现是为 bitmap 设计的,这两者我们都可以用:
Glide
.with(context)
.load(url)
.transform(new FillSpace())
//.bitmapTransform(new FillSpace()) // this would work too!
.into( imageView );
注意
请特别注意,对于任何 Transformation 子类,包括 BitmapTransformation,有三个方法 必须 实现它们,以使得磁盘和内存缓存正确地工作。如果没有复写equals()和hashCode(),BitmapTransformation 和 Transformation 也能通过编译,但这并不意味着它们能正常工作。
ImageView的自动变换
在Glide中,当一个 ImageView 开始加载时,Glide可能会自动应用 FitCenter 或 CenterCrop ,这取决于view的 ScaleType 。如果 scaleType 是 CENTER_CROP , Glide 将会自动应用 CenterCrop 变换。如果 scaleType 为 FIT_CENTER 或 CENTER_INSIDE ,Glide会自动使用 FitCenter 变换。
我们可以覆写默认的变换,只需要一个带有 Transformation 集合的 RequestOptions 即可。另外也可以通过使用 dontTransform() 确保不会自动应用任何变换。
目标
关于Target
在Glide中,Target 是介于请求和请求者之间的中介者的角色。Target 负责展示占位符,加载资源,并为每个请求决定合适的尺寸。被使用得最频繁的是 ImageViewTargets ,它用于在 ImageView 上展示占位符、Drawable 和 Bitmap 。
指定目标
into(Target) 方法不仅仅用于启动每个请求,它同时也指定了接收请求结果的 Target:
Target<Drawable> target =
Glide.with(context)
.load(url)
.into(new Target<Drawable>() {
...
});
Glide 提供了一个辅助方法 into(ImageView) ,它接受一个 ImageView 参数并为其请求的资源类型包装了一个合适的 ImageViewTarget:
Target<Drawable> target =
Glide.with(context)
.load(url)
.into(imageView);
取消和重用
into(Target) 和 into(ImageView) 都返回了一个 Target 实例。重用这个 Target 来在将来开始一个新的加载,之前开始的任何请求都会被取消,它们使用的资源将被释放。
也可以使用返回的 Target 来 clear() 之前的加载,这将在不需要开始新的加载的情况下释放掉相关资源。
Target<Drawable> target =
Glide.with(fragment)
.load(url)
.into(new Target<Drawable>() {
...
});
...
// Some time in the future:
Glide.with(context)
.load(newUrl)
.into(target);
// Some time in the future:
Glide.with(context).clear(target);
//与加载到imageView类似
Glide.with(context)
.load(newUrl)
.into(imageView);
Glide.with(context).clear(imageView);
SimpleTarget
指定尺寸
SimpleTarget target = new SimpleTarget<Bitmap>( 250, 250 ) {
@Override
public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
imageView.setImageBitmap( bitmap );
}
};
Glide.with( context.getApplicationContext() ) // safer!
.load( url )
.asBitmap()
.into( target );
动画资源
Glide.with(context)
.load(url)
.into(new SimpleTarget<>() {
@Override
public void onResourceReady(Drawable resource, Transition<GifDrawable> transition) {
if (resource instanceof Animatable) {
resource.start();
}
// Set the resource wherever you need to use it.
}
});
ViewTarget
Glide 并不支持加载图片到自定义 view 中,所以可以使用ViewTarget 来实现。
CustomView customView = (CustomView) findViewById( R.id.custom_view );
viewTarget = new ViewTarget<CustomView, GlideDrawable>( customView ) {
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
//view.setImag是自定义view里自己去实现的方法
this.view.setImage( resource.getCurrent() );
}
};
Glide
.with( context)
.load( url )
.into( viewTarget );
Target下载图片文件
val future: FutureTarget<File> = Glide.with(context)
.load(url)
.downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
val cacheFile: File = future.get()
清理
当你完成了对资源的使用时,需要及时清理创建的这些 Target 。即使请求已经完成了,也应该使用 clear() 以使 Glide 可以重用被这次加载使用的资源 (特别是 Bitmap )。未调用 clear() 会浪费 CPU 和内存,阻塞更重要的加载,甚至如果你在同一个 surface (View, Notification, RPC 等) 上有两个 Target,可能会引发图片显示错误。对于像 SimpleTarget这种无法从一个新实例里跟踪前一个请求的 Target 来说,及时清理尤为重要。
缓存
默认情况下,Glide 会在开始一个新的图片请求之前检查以下多级的缓存:
1.活动资源 (Active Resources) – 现在是否有另一个 View 正在展示这张图片
2.内存缓存 (Memory cache) – 该图片是否最近被加载过并仍存在于内存中
3.资源类型(Resource) – 该图片是否之前曾被解码、转换并写入过磁盘缓存
4.数据来源 (Data) – 构建这个图片的资源是否之前曾被写入过文件缓存
前两步检查图片是否在内存中,如果是则直接返回图片。
后两步则检查图片是否在磁盘上,以便快速但异步地返回图片。
如果四个步骤都未能找到图片,则Glide会返回到原始资源以取回数据(原始文件,Uri, Url等)。
磁盘缓存策略
DiskCacheStrategy 可被 diskCacheStrategy 方法应用到每一个单独的请求。
DiskCacheStrategy.NONE ————-什么都不缓存
DiskCacheStrategy.DATA ————- 仅仅只缓存原来的全分辨率的图像。
DiskCacheStrategy.RESOURCE —–仅仅缓存最终的图像,即,降低分辨率后的(或者是转换后的)
DiskCacheStrategy.ALL —————-缓存所有版本的图像
DiskCacheStrategy.AUTOMATIC —-让Glide根据图片资源智能地选择使用哪一种缓存策略(默认选项)
跳过磁盘缓存
Glide.with(context)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(view);
跳过内存缓存
Glide.with(context)
.load(url)
.skipMemoryCache(true)
.into(view);
仅从缓存加载图片
Glide.with(context)
.load(url)
.onlyRetrieveFromCache(true)
.into(imageView);
清理缓存
Glide.get(context).clearDiskCache();//只能在子线程执行
Glide.get(context).clearMemory();//只能在主线程执行
调试
打开日志
Glide 的 GeneralRequest 类提供了一个方法去设置 log 的级别。需要用shell命令打开。
adb shell setprop log.tag.GenericRequest DEBUG
RequestListener
Glide.with(fragment)
.load(url)
.listener(new RequestListener() {
@Override
boolean onLoadFailed(@Nullable GlideException e, Object model,
Target<R> target, boolean isFirstResource) {
Log.e(TAG, "Load failed", e);
return false; // Allow calling onLoadFailed on the Target.
}
@Override
boolean onResourceReady(R resource, Object model, Target<R> target,
DataSource dataSource, boolean isFirstResource) {
return false; // Allow calling onResourceReady on the Target.
}
})
// .error(R.drawable.error)
.into(imageView);
Module
Glide module 是一个抽象方法,全局改变 Glide 行为的一个方式。
自定义Module可以实现定制缓存大小、图片池大小以及改变解码规则等等功能,属于Glide的高阶使用技巧,本文不作展开。
参考资料
Glide官方文档:https://muyangmin.github.io/glide-docs-cn/
Glide系列博客:https://mrfu.me/2016/02/27/Glide_Getting_Started/ 作者:Yuan Fu
原文地址:https://blog.csdn.net/weixin_49078536/article/details/126787387
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_37702.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!