private void getImageCode(boolean isClear) { mPbLoading.setVisibility(ProgressBar.VISIBLE); //加载菊花圈 mTxtErrorNotice.setVisibility(View.GONE);//显示图片加载失败或者错误的文字,如果没这个需求则直接用glide的展位图即可 if (isClear) { ACache mCache = ACache.get(this.getContext());轻量级缓存框架 //https://github.com/yangfuhai/ASimpleCache Bitmap imagecode = mCache.getAsBitmap("imagecode"); if (imagecode != null) { mImageCode.setImageBitmap(imagecode); mPbLoading.setVisibility(ProgressBar.GONE); return; } } if (mSimpleTarget == null) { mSimpleTarget = new SimpleTarget<Bitmap>() { @Override public void onResourceReady(@android.support.annotation.NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) { mPbLoading.setVisibility(ProgressBar.GONE); mTxtErrorNotice.setVisibility(View.GONE); mImageCode.setVisibility(View.VISIBLE); mImageCode.setImageBitmap(resource); ACache mCache = ACache.get(this.getContext());轻量级缓存框架//https://github.com/yangfuhai/ASimpleCache mCache.put("imagecode", resource, 200); } @Override public void onLoadFailed(@Nullable Drawable errorDrawable) { super.onLoadFailed(errorDrawable); mPbLoading.setVisibility(ProgressBar.GONE); mTxtErrorNotice.setVisibility(View.VISIBLE); mImageCode.setVisibility(View.INVISIBLE); } }; } String updateTime = String.valueOf(System.currentTimeMillis()); // 在需要重新获取更新的图片时调用 GlideApp.with(this) .asBitmap() .load(UrlConstants.ImageCodeUrl) .signature(new ObjectKey(updateTime)) .into(mSimpleTarget); Timber.tag("imagecode"); Timber.e("getImageCode"); }
布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <ImageView android:layout_marginRight="@dimen/px5" android:layout_marginTop="@dimen/px10" android:id="@+id/imageview_cancel" android:layout_width="@dimen/px49" android:layout_height="@dimen/px49" android:layout_gravity="right" android:layout_marginBottom="@dimen/px10" android:src="@mipmap/image_app_upload_dialog_cancel"/> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/shape_alert_bg" android:paddingBottom="@dimen/px20" android:paddingLeft="@dimen/px20" android:paddingRight="@dimen/px20" android:paddingTop="@dimen/px20" > <ImageView android:id="@+id/iv_image_code" android:layout_width="match_parent" android:layout_height="@dimen/px150" android:layout_marginLeft="@dimen/px20" android:layout_marginRight="@dimen/px20"/> <TextView android:id="@+id/txt_error_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="@dimen/px60" android:gravity="center" android:text="获取失败,点击重试" android:textSize="@dimen/font_24px" android:visibility="gone" tools:visibility="visible"/> <ProgressBar android:id="@+id/progress_wheel_load" style="?android:attr/progressBarStyleLarge" android:layout_width="@dimen/px50" android:layout_height="@dimen/px50" android:layout_centerHorizontal="true" android:layout_marginTop="@dimen/px40" android:indeterminateBehavior="repeat" android:indeterminateDrawable="@drawable/shape_state_progress" android:indeterminateDuration="600" android:indeterminateOnly="true" android:visibility="visible" tools:visibility="visible" /> <TextView android:id="@+id/txt_reset_image_code" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/iv_image_code" android:layout_centerHorizontal="true" android:layout_marginTop="@dimen/px20" android:text="看不清楚?点击刷新" /> <TextView android:visibility="gone" tools:visibility="visible" android:id="@+id/txt_error_input_notice" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/txt_reset_image_code" android:layout_centerHorizontal="true" android:layout_marginTop="@dimen/px20" android:text="图形验证码错误,请重新输入!" android:textColor="@color/red" /> <!--android:inputType="number"--> <EditText android:id="@+id/edit_image_code" android:layout_width="match_parent" android:layout_height="@dimen/px140" android:layout_below="@+id/txt_reset_image_code" android:background="@null" android:gravity="bottom|center_horizontal" android:hint="请输入图形验证码" android:digits="0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM" android:maxLength="5" android:paddingBottom="@dimen/px15" android:paddingLeft="@dimen/px20" android:paddingRight="@dimen/px20" android:textColorHint="#969696" android:textCursorDrawable="@drawable/shape_login_edittext_cursor_color" android:textSize="@dimen/font_32px"/> <View android:id="@+id/view_divider1" android:layout_width="match_parent" android:layout_height="@dimen/px1" android:layout_below="@+id/edit_image_code" android:layout_marginLeft="@dimen/px20" android:layout_marginRight="@dimen/px20" android:background="#e5e5e5"/> <Button android:id="@+id/bt_send_sms_code" style="?android:attr/borderlessButtonStyle" android:layout_width="@dimen/px230" android:layout_height="@dimen/px80" android:layout_below="@+id/view_divider1" android:layout_centerHorizontal="true" android:layout_marginLeft="@dimen/px20" android:layout_marginRight="@dimen/px20" android:layout_marginTop="@dimen/px20" android:background="@drawable/yeyout_def_btn_bg_selector" android:clickable="true" android:gravity="center" android:text="确定" android:textColor="#FFF" android:textSize="@dimen/font_32px"/> </RelativeLayout> </LinearLayout>
以上我是使用Acache根据时间自己缓存了图片,其实是没有必要的,因为glide是自带这样效果的,直接设置自定义缓存key就好. 可以参考 Android-图片框架之Glide添加水印文字,模糊效果以及分析Glide 实现效果
自定义key需要实现Glide的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;
}
//在此处做根据时间去判断更新现有的图片即可(根据时间戳判断并调用update方法)
@Override
public void updateDiskCacheKey(MessageDigest messageDigest) {
messageDigest.update(ByteBuffer.allocate(Integer.SIZE).putInt(signature).array());
}
}
因为懒癌发作,所以此处我没有给出根据时间去更新缓存的代码(后续再更新),只是给出了基本的复写方法哦。
分析原理:
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与其他开源图片框架不同的地方,它会根据手机屏幕,图片转换后的大小,显示的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);
如果这些努力都无法奏效,您不能更改标识符,也不能跟踪任何合理的版本元数据的情况下,也可以使用 diskCacheStrategy()
和 DiskCacheStrategy.NONE
来完全禁用磁盘缓存。
参考自Glide中文文档 https://muyangmin.github.io/glide-docs-cn/doc/caching.html