Glide v4 知识点总结
来源:互联网 发布:圆形玻璃定制淘宝 编辑:程序博客网 时间:2024/05/18 00:55
性能提示
Android中的动画代价是比较大的,尤其是同时开始大量动画的时候。 交叉淡入和其他涉及 alpha 变化的动画显得尤其昂贵。 此外,动画通常比图片解码本身还要耗时。在列表和网格中滥用动画可能会让图像的加载显得缓慢而卡顿。为了提升性能,请在使用 Glide 向 ListView , GridView, 或 RecyclerView 加载图片时考虑避免使用动画,尤其是大多数情况下,你希望图片被尽快缓存和加载的时候。作为替代方案,请考虑预加载,这样当用户滑动到具体的 item 的时候,图片已经在内存中了。
在 ListView 和 RecyclerView 中的使用
在 ListView 或 RecyclerView 中加载图片的代码和在单独的 View 中加载完全一样。Glide 已经自动处理了 View 的复用和请求的取消:
@Overridepublic void onBindViewHolder(ViewHolder holder, int position) { String url = urls.get(position); Glide.with(fragment) .load(url) .into(holder.imageView);}
对 url 进行 null 检验并不是必须的,如果 url 为 null,Glide 会清空 View 的内容,或者显示 placeholder Drawable 或 fallback Drawable 的内容。
Glide 唯一的要求是,对于任何可复用的 View 或 Target ,如果它们在之前的位置上,用 Glide 进行过加载操作,那么在新的位置上要去执行一个新的加载操作,或调用 clear() API 停止 Glide 的工作。
@Overridepublic void onBindViewHolder(ViewHolder holder, int position) { if (isImagePosition(position)) { String url = urls.get(position); Glide.with(fragment) .load(url) .into(holder.imageView); } else { Glide.with(fragment).clear(holder.imageView); holder.imageView.setImageDrawable(specialDrawable); }}
对 View 调用 clear() 或 into(View),表明在此之前的加载操作会被取消,并且在方法调用完成后,Glide 不会改变 view 的内容。如果你忘记调用 clear(),而又没有开启新的加载操作,那么就会出现这种情况,你已经为一个 view 设置好了一个 Drawable,但该 view 在之前的位置上使用 Glide 进行过加载图片的操作,Glide 加载完毕后可能会将这个 view 改回成原来的内容。
这里的代码以 RecyclerView 的使用为例,但规则同样适用于 ListView。
占位符
类型
- 占位符(Placeholder)
- 错误符(Error)
- 后备回调符(Fallback)
- 占位符(Placeholder)
占位符是当请求正在执行时被展示的 Drawable 。当请求成功完成时,占位符会被请求到的资源替换。如果被请求的资源是从内存中加载出来的,那么占位符可能根本不会被显示。如果请求失败并且没有设置 error Drawable ,则占位符将被持续展示。类似地,如果请求的url/model为 null ,并且 error Drawable 和 fallback 都没有设置,那么占位符也会继续显示。
使用 generated API :
GlideApp.with(fragment) .load(url) .placeholder(R.drawable.placeholder) .into(view);
Or:
GlideApp.with(fragment) .load(url) .placeholder(new ColorDrawable(Color.BLACK)) .into(view);
- 错误符(Error)
error Drawable 在请求永久性失败时展示。error Drawable 同样也在请求的url/model为 null ,且并没有设置 fallback Drawable 时展示。
With the generated API:
GlideApp.with(fragment) .load(url) .error(R.drawable.error) .into(view);
Or:
GlideApp.with(fragment) .load(url) .error(new ColorDrawable(Color.RED)) .into(view);
- 后备回调符(Fallback)
fallback Drawable 在请求的url/model为 null 时展示。设计 fallback Drawable 的主要目的是允许用户指示 null 是否为可接受的正常情况。例如,一个 null 的个人资料 url 可能暗示这个用户没有设置头像,因此应该使用默认头像。然而,null 也可能表明这个元数据根本就是不合法的,或者取不到。 默认情况下Glide将 null 作为错误处理,所以可以接受 null 的应用应当显式地设置一个 fallback Drawable 。
使用 generated API:
GlideApp.with(fragment) .load(url) .fallback(R.drawable.fallback) .into(view);
Or:
GlideApp.with(fragment) .load(url) .fallback(new ColorDrawable(Color.GREY)) .into(view);
Generated API
使用
- 在 Application 模块中包含一个 AppGlideModule 的实现:
@GlideModulepublic final class MyAppGlideModule extends AppGlideModule {}
你不必去重写 AppGlideModule 中的任何一个方法。子类中完全可以不用写任何东西,它只需要继承 AppGlideModule 并且添加 @GlideModule 注解。
AppGlideModule 的实现必须使用 @GlideModule 注解标记。如果注解不存在,该 module 将不会被 Glide 发现,并且在日志中收到一条带有 Glide tag 的警告,表示 module 未找到。
- 使用 Generated API
Generated API 默认名为 GlideApp ,与 Application 模块中 AppGlideModule的子类包名相同。在 Application 模块中将 Glide.with() 替换为 GlideApp.with(),即可使用该 API 去完成加载工作:
GlideApp.with(fragment)
.load(myUrl)
.placeholder(R.drawable.placeholder)
.fitCenter()
.into(imageView);
与 Glide.with() 不同,诸如 fitCenter() 和 placeholder() 等选项在 Builder 中直接可用,并不需要再传入单独的 RequestOptions 对象。
- 注意
Android Studio 在大多数时候都可以正确地处理注解处理器 (annotation processor) 和 generated API。然而,当你第一次添加你的 AppGlideModule 或做了某些类型的修改后,你可能需要重新构建 (rebuild) 你的项目。 无论何时,如果你发现 API 没有被 import ,或看起来已经过期,你可以通过以下方法重新构建:
- 打开 Build 菜单;
- 点击 Rebuild Project。
GlideExtension
Glide Generated API 可在 Application 和 Library 中被扩展。扩展使用被注解的静态方法来添加新的选项、修改现有选项、甚至添加额外的类型支持。
@GlideExtension 注解用于标识一个扩展 Glide API 的类。任何扩展 Glide API 的类都必须使用这个注解来标记,否则其中被注解的方法就会被忽略。
被 @GlideExtension 注解的类应以工具类的思维编写。这种类应该有一个私有的、空的构造方法,应为 final 类型,并且仅包含静态方法。被注解的类可以含有静态变量,可以引用其他的类或对象。
在 Application 模块中可以根据需求实现任意多个被 @GlideExtension 注解的类,在 Library 模块中同样如此。当 AppGlideModule 被发现时,所有有效的 Glide 扩展类 会被合并,所有的选项在 API 中均可以被调用。合并冲突会导致 Glide 的 Annotation Processor 抛出编译错误。
被 @GlideExtention 注解的类有两种扩展方式:
- GlideOption - 为 RequestOptions 添加一个自定义的选项。
- GlideType - 添加对新的资源类型的支持(GIF,SVG 等等)。
GlideOption
用 @GlideOption
注解的静态方法用于扩展 RequestOptions 。GlideOption 可以:
定义一个在 Application 模块中频繁使用的选项集合。
创建新的选项,通常与 Glide 的 Option 类一起使用。
要定义一个选项集合,你可以这么写:
@GlideExtensionpublic class MyAppExtension { // Size of mini thumb in pixels. private static final int MINI_THUMB_SIZE = 100; private MyAppExtension() { } // utility class @GlideOption public static void miniThumb(RequestOptions options) { options .fitCenter() .override(MINI_THUMB_SIZE); }
这将会在 RequestOptions 的子类中生成一个方法,类似这样:
public class GlideOptions extends RequestOptions { public GlideOptions miniThumb() { MyAppExtension.miniThumb(this); } ...}
你可以为方法任意添加参数,但要保证第一个参数为 RequestOptions。
@GlideOptionpublic static void miniThumb(RequestOptions options, int size) { options .fitCenter() .override(size);}
在自动生成的方法中新添的参数同样被加了进来:
public GlideOptions miniThumb(int size) { MyAppExtension.miniThumb(this);}
之后你就可以使用生成的 GlideApp 类调用你的自定义方法:
GlideApp.with(fragment) .load(url) .miniThumb(thumbnailSize) .into(imageView);
使用 @GlideOption 标记的方法应该为静态方法,并且返回值为空。请注意,这些生成的方法在一般的 Glide 和 RequestOptions 类里不可用。
GlideType
被 @GlideType 注解的静态方法用于扩展 RequestManager 。被 @GlideType 注解的方法允许你添加对新的资源类型的支持,包括指定默认选项。
例如,为添加对 GIF 的支持,你可以添加一个被 @GlideType 注解的方法:
@GlideExtensionpublic class MyAppExtension { private static final RequestOptions DECODE_TYPE_GIF = decodeTypeOf(GifDrawable.class).lock(); @GlideType(GifDrawable.class) public static void asGif(RequestBuilder<GifDrawable> requestBuilder) { requestBuilder .transition(new DrawableTransitionOptions()) .apply(DECODE_TYPE_GIF); }}
这样会生成一个包含对应方法的 RequestManager :
public class GlideRequests extends RequesetManager { public RequestBuilder<GifDrawable> asGif() { RequestBuilder<GifDrawable> builder = as(GifDrawable.class); MyAppExtension.asGif(builder); return builder; } ...}
之后你可以使用生成的 GlideApp 类调用你的自定义类型:
GlideApp.with(fragment) .asGif() .load(url) .into(imageView);
被 @GlideType 标记的方法必须使用 RequestBuilder 作为其第一个参数,这里的泛型 对应 @GlideType 注解中传入的类。该方法应为静态方法,且返回值为空。方法必须定义在一个被 @GlideExtension 注解标记的类中。
请求选项
Glide中的大部分设置项都可以通过 RequestOptions 类和 apply() 方法来应用到程序中。
使用 request options 可以实现(包括但不限于):
- 占位符(Placeholders)
- 转换(Transformations)
- 缓存策略(Caching Strategies)
- 组件特有的设置项,例如编码质量,或Bitmap的解码配置等。
过渡选项
TransitionOptions 用于决定你的加载完成时会发生什么。
使用 TransitionOption 可以应用以下变换:
- View淡入
- 与占位符交叉淡入
- 或者什么都不发生
RequestBuilder
RequestBuilder 是Glide中请求的骨架,负责携带请求的url和你的设置项来开始一个新的加载过程。
使用 RequestBuilder 可以指定:
- 你想加载的资源类型(Bitmap, Drawable, 或其他)
- 你要加载的资源地址(url/model)
- 你想最终加载到的View
- 任何你想应用的(一个或多个)RequestOption 对象
- 任何你想应用的(一个或多个)TransitionOption 对象
- 任何你想加载的缩略图 thumbnail()
选择资源类型
RequestBuilders 是特定于它们将要加载的资源类型的。默认情况下你会得到一个 Drawable RequestBuilder ,但你可以使用 as… 系列方法来改变请求类型。例如,如果你调用了 asBitmap() ,你就将获得一个 BitmapRequestBuilder 对象,而不是默认的 Drawable RequestBuilder。
RequestBuilder<Bitmap> requestBuilder = Glide.with(fragment).asBitmap();
RequestOptions
- 可以使用 apply() 方法应用 RequestOptions ;
- 使用 transition() 方法应用 TransitionOptions 。
RequestBuilder<Drawable> requestBuilder = Glide.with(fragment);requestBuilder.apply(requestOptions);requestBuilder.transition(transitionOptions);
RequestBuilder 也可以被复用于开始多个请求:
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 的 thumbnail API 允许你指定一个 RequestBuilder 以与你的主请求并行启动。缩略图 会在主请求加载过程中展示。如果主请求在缩略图请求之前完成,则缩略图请求中的图像将不会被展示。[thumbnail] API 允许你简单快速地加载图像的低分辨率版本,并且同时加载图像的无损版本,这可以减少用户盯着加载指示器 【例如进度条–译者注)】 的时间。
thumbnail() API 对本地和远程图片都适用,尤其是当低分辨率缩略图存在于 Glide 的磁盘缓存时,它们将很快被加载出来。
thumbnail API 使用起来相对简单:
Glide.with(fragment) .load(url) .thumbnail(Glide.with(fragment) .load(thumbnailUrl)) .into(imageView);
只要你的 thumbnailUrl 指向的图片比你的主 url 的分辨率更低,它将会很好地工作。相当数量的加载 API 提供了不同的指定图片尺寸的方法,它们尤其适用于 thumbnail API。
如果你仅仅想加载一个本地图像,或者你只有一个单独的远程 URL, 你仍然可以从缩略图 API 受益。请使用 Glide 的 override 或 sizeMultiplier API 来强制 Glide 在缩略图请求中加载一个低分辨率图像:
int thumbnailSize = ...;Glide.with(fragment) .load(localUri) .thumbnail(Glide.with(fragment) .load(localUri) .override(thumbnailSize)) .into(view);
thumbnail 方法有一个简化版本,它只需要一个 sizeMultiplier 参数。如果你只是想为你的加载相同的图片,但尺寸为 View 或 Target 的某个百分比的话特别有用:
Glide.with(fragment) .load(localUri) .thumbnail(/*sizeMultiplier=*/ 0.25f) .into(imageView);
在失败时开始新的请求
从 Glide 4.3.0 开始,你现在可以使用 error API 来指定一个 RequestBuilder,以在主请求失败时开始一次新的加载。例如,在请求 primaryUrl 失败后加载 fallbackUrl:
Glide.with(fragment) .load(primaryUrl) .error(Glide.with(fragment) .load(fallbackUrl)) .into(imageView);
如果主请求成功完成,这个error RequestBuilder 将不会被启动。如果你同时指定了一个 thumbnail 和一个 error RequestBuilder,则这个后备的 RequestBuilder 将在主请求失败时启动,即使缩略图请求成功也是如此。
目标尺寸测量
默认情况下,Glide 使用 Target 通过 getSize() 方法提供的尺寸作为请求的目标尺寸。这种设计允许 Glide 可以选取合适的 url ,降低采样率,剪裁和转换图像,从而最小化内存的使用,并确保加载尽可能快。
最简单的实现getSize()的方法可能是直接调用库提供的回调:
定制目标
@Overridepublic void getSize(SizeReadyCallback cb) { cb.onSizeReady(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);}
你也可以向你的 Target 的构造函数传入一个尺寸,并在这个回调中提供这个尺寸:
public class CustomTarget<T> implements Target<T> { private final int width; private final int height; public CustomTarget(int width, int height) { this.width = width; this.height = height; } ... @Override public void getSize(SizeReadyCallback cb) { cb.onSizeReady(width, height); }}
View目标
ViewTarget 通过检查 View 的属性和/或使用一个 OnPreDrawListener 在 View 绘制之前直接测量尺寸来实现 getSize() 方法。我们使用以下逻辑:
- 如果 View 的的宽或高被设置为 > 0,则使用这个尺寸
- 如果 View 的宽或高被设置为 WRAP_CONTENT ,则使用屏幕的宽或高
- 如果仍然至少有一个维度 <= 0 并且不是 WRAP_CONTENT ,添加一个 OnPreDrawListener 监听布局。
## WRAP_CONTENT
请注意,Glide 可能对 WRAP_CONTENT 处理不是特别好。这是因为我们很难知道用户的实际意图,尤其是还请求了变换(Transformations)的时候。
我们可以将 WRAP_CONTENT 视为用户请求原始的未修改的图像,但这么做会有在加载超大图像时导致 OutOfMemoryException 的风险。另外,尤其是因为View通常不会超出屏幕,Android Framework 最后可能会将我们设法成功加载的任意高分辨率图像给缩小(downscaling)。
使用屏幕尺寸,至少允许我们缩小超大的图片,而又不完全忽略用户的原始请求意图。
尺寸与性能
一般来说,在加载图片的 View 被设置了显式的dp尺寸的情况下,Glide 提供了最快、最可预测的结果。在不可能获得明确的 dp 尺寸时,Glide 也通过使用 OnPreDrawListeners 为 layout weight, MATCH_PARENT 以及其他相对尺寸提供了相当鲁棒的支持。如果这些都不奏效,Glide 也为 WRAP_CONTENT 提供了应该较为合理的行为。
其他情况
在任何情况下,如果 Glide 看起来获取了错误的 View 尺寸,你都可以手动覆盖来纠正它。你可以选择扩展 ViewTarget 实现你自己的逻辑,或者使用 RequestOption 里的方法。
过渡
标准行为
Glide 提供了很多的过渡效果,用户可以手动地应用于每个请求。Glide 的内置过渡以一致的方式运行,并且将根据加载图像的位置在某些情况下避免运行。
在 Glide 中,图像可能从四个地方中的任何一个位置加载出来:
- Glide 的内存缓存
- Glide 的磁盘缓存
- 设备本地可用的一个源文件或 Uri
- 仅远程可用的一个源 Url 或 Uri
如果图像从 Glide 的内存缓存中加载出来,Glide 的内置过渡将不会执行。然而,在另外三种场景下,Glide 的内置过渡都会被执行。
常见错误
- 对占位符和透明图片交叉淡入
Glide 的默认交叉淡入(cross fade)效果使用了 TransitionDrawable 。它提供两种动画模式,由 setCrossFadeEnabled() 控制。当交叉淡入被禁用时,正在过渡的图片会在原先显示的图像上面淡入。当交叉淡入被启用时,原先显示的图片会从不透明过渡到透明,而正在过渡的图片则会从透明变为不透明。
在 Glide 中,我们默认禁用了交叉淡入,这样通常看起来要好看一些。实际的交叉淡入,如上所述对两个图片同时改变 alpha 值,通常会在过渡的中间造成一个短暂的白色闪屏,这个时候两个图片都是部分不透明的。
不幸的是,虽然禁用交叉淡入通常是一个比较好的默认行为,当待加载的图片包含透明像素时仍然可能造成问题。当占位符比实际加载的图片要大,或者图片部分为透明时,禁用交叉淡入会导致动画完成后占位符在图片后面仍然可见。如果你在加载透明图片时使用了占位符,你可以启用交叉淡入,具体办法是调整 DrawableCrossFadeFactory 里的参数并将结果传到 transition() 中。
- 在多个请求间交叉淡入
Transitions 并不能让你在不同请求中加载的两个图像之间做过渡。当新的加载被应用到 View 或 Target (查看 Target的文档 )上时,Glide 默认会取消任何已经存在的请求。因此,如果你想加载连个个不同的图片并在它们之间做动画,你无法直接通过 Glide 来完成。等待第一个加载完成并在 View 外持有这个 Bitmap 或 Drawable ,然后开始新的加载并手动在这两者之间做动画,诸如此类的策略看起来有效,但是实际上不安全,并可能导致程序崩溃或图像错误。
相反,最简单的办法是使用包含两个 ImageView 的 ViewSwitcher 来完成。将第一张图片加载到 getNextView() 的返回值里面,然后将第二张图片加载到 getNextView() 的下一个返回值中,并使用一个 RequestListener 在第二张图片加载完成时调用 showNext() 。为了更好地控制,你也可以使用 Android开发者文档 指出的策略。但要记住与 ViewSwitcher 一样,仅在第二次图像加载完成后才开始交叉淡入淡出。
定制过渡
如果要定义一个自定义的过渡动画,你需要完成以下两个步骤:
- 实现 TransitionFactory .
- 使用 DrawableTransitionOptions#with 来将你自定义的 TransitionFactory 应用到加载中。
如果要改变你的 transition 的默认行为,以更好地控制它在不同的加载源(内存缓存,磁盘缓存,或uri)下是否被应用,你可以检查一下你的 TransitionFactory 中传递给 build() 方法的那个 DataSource 。
Glide里的缓存
默认情况下,Glide 会在开始一个新的图片请求之前检查以下多级的缓存:
- 活动资源 (Active Resources) - 现在是否有另一个 View 正在展示这张图片?
- 内存缓存 (Memory cache) - 该图片是否最近被加载过并仍存在于内存中?
- 资源类型(Resource) - 该图片是否之前曾被解码、转换并写入过磁盘缓存?
- 数据来源 (Data) - 构建这个图片的资源是否之前曾被写入过文件缓存?
前两步检查图片是否在内存中,如果是则直接返回图片。后两步则检查图片是否在磁盘上,以便快速但异步地返回图片。
如果四个步骤都未能找到图片,则Glide会返回到原始资源以取回数据(原始文件,Uri, Url等)。
关于 Glide 缓存的默认大小与它们在磁盘上的位置的更多细节,或如何配置这些参数,请查看 配置 页面。
缓存键(Cache Keys)
在 Glide v4 里,所有缓存键都包含至少两个元素:
- 请求加载的 model(File, Url, Url)
一个可选的 签名(Signature)
另外,步骤1-3(活动资源,内存缓存,资源磁盘缓存)的缓存键还包含一些其他数据,包括:宽度和高度
- 可选的变换(Transformation)
- 额外添加的任何 选项(Options)
- 请求的数据类型 (Bitmap, GIF, 或其他)
活动资源和内存缓存使用的键还和磁盘资源缓存略有不同,以适应内存 选项(Options),比如影响 Bitmap 配置的选项或其他解码时才会用到的参数。
为了生成磁盘缓存上的缓存键名称,以上的每个元素会被哈希化以创建一个单独的字符串键名,并在随后作为磁盘缓存上的文件名使用。
配置缓存
Glide 提供一系列的选项,以允许你选择加载请求与 Glide 缓存如何交互。
磁盘缓存策略(Disk Cache Strategy)
DiskCacheStrategy 可被 diskCacheStrategy 方法应用到每一个单独的请求。 目前支持的策略允许你阻止加载过程使用或写入磁盘缓存,选择性地仅缓存无修改的原生数据,或仅缓存变换过的缩略图,或是兼而有之。
默认的策略叫做 AUTOMATIC ,它会尝试对本地和远程图片使用最佳的策略。当你加载远程数据(比如,从URL下载)时,AUTOMATIC 策略仅会存储未被你的加载过程修改过(比如,变换,裁剪–译者注)的原始数据,因为下载远程数据相比调整磁盘上已经存在的数据要昂贵得多。对于本地数据,AUTOMATIC 策略则会仅存储变换过的缩略图,因为即使你需要再次生成另一个尺寸或类型的图片,取回原始数据也很容易。
指定 DiskCacheStrategy 非常容易:
GlideApp.with(fragment) .load(url) .diskCacheStrategy(DiskCacheStrategy.ALL) .into(imageView);
- 仅从缓存加载图片
某些情形下,你可能希望只要图片不在缓存中则加载直接失败(比如省流量模式?–译者注)。如果要完成这个目标,你可以在单个请求的基础上使用 onlyRetrieveFromCache 方法:
GlideApp.with(fragment) .load(url) .onlyRetrieveFromCache(true) .into(imageView);
如果图片在内存缓存或在磁盘缓存中,它会被展示出来。否则只要这个选项被设置为 true ,这次加载会视同失败。
- 跳过缓存
如果你想确保一个特定的请求跳过磁盘和/或内存缓存(比如,图片验证码 –译者注),Glide 也提供了一些替代方案。
仅跳过内存缓存,请使用 skipMemoryCache() :
GlideApp.with(fragment) .load(url) .skipMemoryCache(true) .into(view);
仅跳过磁盘缓存,请使用 DiskCacheStrategy.NONE :
GlideApp.with(fragment) .load(url) .diskCacheStrategy(DiskCacheStrategy.NONE) .into(view);
这两个选项可以同时使用:
GlideApp.with(fragment) .load(url) .diskCacheStrategy(DiskCacheStrategy.NONE) .skipMemoryCache(true) .into(view);
虽然提供了这些办法让你跳过缓存,但你通常应该不会想这么做。从缓存中加载一个图片,要比拉取-解码-转换成一张新图片的完整流程快得多。
缓存的刷新
因为磁盘缓存使用的是哈希键,所以并没有一个比较好的方式来简单地删除某个特定url或文件路径对应的所有缓存文件。如果你只允许加载或缓存原始图片的话,问题可能会变得更简单,但因为Glide还会缓存缩略图和提供多种变换(transformation),它们中的任何一个都会导致在缓存中创建一个新的文件,而要跟踪和删除一个图片的所有版本无疑是困难的。
在实践中,使缓存文件无效的最佳方式是在内容发生变化时(url,uri,文件路径等)更改你的标识符。
定制缓存刷新策略
因为通常改变标识符比较困难或者根本不可能,所以Glide也提供了 签名 API 来混合(你可以控制的)额外数据到你的缓存键中。签名(signature)适用于媒体内容,也适用于你可以自行维护的一些版本元数据。
- MediaStore 内容 - 对于媒体存储内容,你可以使用Glide的 MediaStoreSignature 类作为你的签名。MediaStoreSignature 允许你混入修改时间、MIME类型,以及item的方向到缓存键中。这三个属性能够可靠地捕获对图片的编辑和更新,这可以允许你缓存媒体存储的缩略图。
- 文件 - 你可以使用 ObjectKey 来混入文件的修改日期。
- Url - 尽管最好的让 url 失效的办法是让 server 保证在内容变更时对URL做出改变,你仍然可以使用 ObjectKey 来混入任意数据(比如版本号)。
将签名传入加载请求很简单:
GlideApp.with(yourFragment) .load(yourFileDataModel) .signature(new ObjectKey(yourVersionMetadata)) .into(yourImageView);
媒体存储签名对于 MediaStore 数据来说也很直接:
GlideApp.with(fragment) .load(mediaStoreUri) .signature(new MediaStoreSignature(mimeType, dateModified, orientation)) .into(view);
你还可以定义你自己的签名,只要实现 Key 接口就好。请确保正确地实现 equals(), hashCode() 和 updateDiskCacheKey() 方法:
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) { md.update(ByteBuffer.allocate(Integer.SIZE).putInt(currentVersion).array()); }}
请记住,为了避免降低性能,您将需要在后台批量加载任何版本元数据,以便在要加载图像时即已处于可用状态。
如果这些努力都无法奏效,您不能更改标识符,也不能跟踪任何合理的版本元数据的情况下,也可以使用 diskCacheStrategy() 和 DiskCacheStrategy.NONE 来完全禁用磁盘缓存。
缓存配置
内存缓存
默认情况下,Glide使用 LruResourceCache ,这是 MemoryCache 接口的一个缺省实现,使用固定大小的内存和 LRU 算法。LruResourceCache 的大小由 Glide 的 MemorySizeCalculator 类来决定,这个类主要关注设备的内存类型,设备 RAM 大小,以及屏幕分辨率。
应用程序可以自定义 MemoryCache 的大小,具体是在它们的 AppGlideModule 中使用 applyOptions(Context, GlideBuilder) 方法配置 MemorySizeCalculator :
@GlideModulepublic class YourAppGlideModule extends AppGlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context) .setMemoryCacheScreens(2) .build(); builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize())); }}
也可以直接覆写缓存大小:
@GlideModulepublic class YourAppGlideModule extends AppGlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { int memoryCacheSizeBytes = 1024 * 1024 * 20; // 20mb builder.setMemoryCache(new LruResourceCache(memoryCacheSizeBytes)); }}
甚至可以提供自己的 MemoryCache 实现:
@GlideModulepublic class YourAppGlideModule extends AppGlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { builder.setMemoryCache(new YourAppMemoryCacheImpl()); }}
磁盘缓存
Glide 使用 DiskLruCacheWrapper 作为默认的 磁盘缓存 。 DiskLruCacheWrapper 是一个使用 LRU 算法的固定大小的磁盘缓存。默认磁盘大小为 250 MB ,位置是在应用的 缓存文件夹 中的一个 特定目录 。
假如应用程序展示的媒体内容是公开的(从无授权机制的网站上加载,或搜索引擎等),那么应用可以将这个缓存位置改到外部存储:
@GlideModulepublic class YourAppGlideModule extends AppGlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { builder.setDiskCache(new ExternalDiskCacheFactory(context)); }}
无论使用内部或外部磁盘缓存,应用程序都可以改变磁盘缓存的大小:
@GlideModulepublic class YourAppGlideModule extends AppGlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { int diskCacheSizeBytes = 1024 1024 100; 100 MB builder.setDiskCache(new InternalDiskCacheFactory(context, diskCacheSizeBytes)); }}
应用程序还可以改变缓存文件夹在外存或内存上的名字:
@GlideModulepublic class YourAppGlideModule extends AppGlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { int diskCacheSizeBytes = 1024 1024 100; 100 MB builder.setDiskCache( new InternalDiskCacheFactory(context, cacheFolderName, diskCacheSizeBytes)); }}
应用程序还可以自行选择 DiskCache 接口的实现,并提供自己的 DiskCache.Factory 来创建缓存。Glide 使用一个工厂接口来在后台线程中打开 磁盘缓存 ,这样方便缓存做诸如检查路径存在性等的IO操作而不用触发 严格模式 。
@GlideModulepublic class YourAppGlideModule extends AppGlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { builder.setDiskCache(new DiskCache.Factory() { @Override public DiskCache build() { return new YourAppCustomDiskCache(); } }); }}
配置
默认请求选项
虽然 请求选项 通常由每个请求单独指定,你也可以通过 AppGlideModule 应用一个 请求选项 的集合以作用于你应用中启动的每个加载:
@GlideModulepublic class YourAppGlideModule extends AppGlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { builder.setDefaultRequestOptions( new RequestOptions() .format(DecodeFormat.RGB_565) .disallowHardwareBitmaps()); }}
一旦你创建了新的请求,这些选项将通过 GlideBuilder 中的 setDefaultRequestOptions 被应用上。因此,任何单独请求里应用的选项将覆盖 GlideBuilder 里设置的冲突选项。
类似地,RequestManagers 允许你为这个特定的 RequestManager 启动的所有加载请求设置默认的 请求选项。 因为每个 Activity 和 Fragment 都拥有自己的 RequestManager,你可以使用 RequestManager 的 applyDefaultRequestOptions 方法来设置默认的 RequestOption,并仅作用于一个特定的 Activity 或 Fragment:
Glide.with(fragment) .applyDefaultRequestOptions( new RequestOptions() .format(DecodeFormat.RGB_565) .disallowHardwareBitmaps());
RequestManager 还有一个 setDefaultRequestOptions 方法,可以完全替换掉之前设置的任意的默认 请求选项,无论它是通过 AppGlideModule 的 [GlideBuilder] 还是 RequestManager。使用 [setDefaultRequestOptions]要小心,因为很容易意外覆盖掉你其他地方设置的重要默认选项。 通常 applyDefaultRequestOptions更安全,使用起来更直观。
未捕获异常策略 (UncaughtThrowableStrategy)
在加载图片时假如发生了一个异常 (例如, OOM), Glide 将会使用一个 GlideExecutor.UncaughtThrowableStrategy 。
默认策略是将异常打印到设备的 LogCat 中。 这个策略从 Glide 4.2.0 起将可被定制。 你可以传入一个磁盘执行器和/或一个 resize 执行器:
@GlideModulepublic class YourAppGlideModule extends AppGlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { final UncaughtThrowableStrategy myUncaughtThrowableStrategy = new ... builder.setDiskCacheExecutor(newDiskCacheExecutor(myUncaughtThrowableStrategy)); builder.setResizeExecutor(newSourceExecutor(myUncaughtThrowableStrategy)); }}
日志级别
你可以使用 setLogLevel (结合 Android 的 Log 定义的值) 来获取格式化日志的子集,包括请求失败时的日志行。通常来说 Log.VERBOSE 将使日志变得更冗杂,Log.ERROR 会让日志更趋向静默,详细可见 javadoc 。
@GlideModulepublic class YourAppGlideModule extends AppGlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { builder.setLogLevel(Log.DEBUG); }}
- Glide v4 知识点总结
- Glide最新版V4使用指南
- Glide v4 GlideApp
- Glide v4 用法
- Glide v4详解
- Glide V4源码解析
- Glide最新版V4使用指南
- Glide V4的封装使用
- Glide图片缓存知识点
- Glide总结
- Glide从V3到V4的探索
- Glide从V3到V4的探索
- Atitit 图像处理知识点体系知识图谱 路线图attilax总结 v4 qcb.xlsx
- Glide使用总结
- Glide详细使用总结
- Glide使用总结
- Glide框架优势总结
- Glide简单实用总结
- memcpy的使用
- 【Angular2】You seem to not be depending on “@angular/core”. This is an error
- 实用小tool
- 2018年秋招面经
- 连连看的出生
- Glide v4 知识点总结
- 获取字符串的长度(strlen/length)
- ElasticSearch shield安全组件从安装到配置完整版
- Java8 日期/时间(Date Time)API指南
- 支付篇—微信扫码支付
- 共用体的成员与特性
- Java请求一个URL。获取网站返回的数据。
- linux内通过命令如何查看和修改系统时区
- Opencv 基础学习一