之前有写过一篇关于glide的基本使用和相关配置,这篇就给大家分享一下glide在项目中通常会遇到的一些坑及解决方法
目前glide版本已经升级到了4.7.1,所以之前在用3.x版本的朋友,升级到最新版本的Api会有一些不一样的地方,详细不同地方可以参考官方介绍 https://muyangmin.github.io/glide-docs-cn/doc/migrating.html
最新版本配置环境:
implementation 'com.github.bumptech.glide:glide:4.7.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
下面就来看看使用过程中遇到的坑,以下代码都是使用glide 4.7.1的api ,大家注意下。
当后台把用户的头像用地址前缀加用户ID拼接设计成时,往往修改头像后,再用Glide加载会发现头像还是之前的头像,原因很简单,是由于Glide默认加载了缓存的图片,所以导致更改之后地址没变还是加载之前的图片,如需要不加载缓存图片,可以使用如下代码:
public static void display(ImageView imageView, String url) {
if (imageView == null) return;
Glide.with(imageView.getContext())
.load(url)
.apply(new RequestOptions()
.dontAnimate()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE))
.into(imageView);
}
设置圆角图片时,正好布局文件中用到了自定义圆角控件,这时应该这样处理代码如下:
/**
* 设置圆角
* @param imageView
* @param path
* @param dp 圆角度数 90dp宽高一致时为圆形
*/
public static void displayRound(ImageView imageView, String url, int dp) {
RequestOptions options = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.transforms(new CenterCrop(), new GlideRoundTransform(dp));
Glide.with(imageView.getContext()).load(url)
.apply(options)
.transition(new DrawableTransitionOptions().crossFade())
.into(imageView);
}
public class GlideRoundTransform extends BitmapTransformation {
private static float radius = 0f;
public GlideRoundTransform() {
this(4);
}
public GlideRoundTransform(int dp) {
radius = Resources.getSystem().getDisplayMetrics().density * dp;
}
@Override
protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
return roundCrop(pool, toTransform);
}
private static Bitmap roundCrop(BitmapPool pool, Bitmap source) {
if (source == null) return null;
Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
if (result == null) {
result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
paint.setAntiAlias(true);
RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight());
canvas.drawRoundRect(rectF, radius, radius, paint);
return result;
}
public String getId() {
return getClass().getName() + Math.round(radius);
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
}
}
加载大图时会有可能出现OOM,可以控制高宽尺寸来处理,高宽设置一个合理的尺寸即可
public static void display(ImageView imageView, String url) {
if (imageView == null) return;
Glide.with(imageView.getContext())
.load(url)
.apply(new RequestOptions()
.override(180, 180))
.into(imageView);
}
第一次加载图片可能会出现拉伸变形,设置.dontAnimate()
取消动画即可解决
public static void display(ImageView imageView, String url) {
if (imageView == null) return;
Glide.with(imageView.getContext())
.load(url)
.apply(new RequestOptions().dontAnimate())
.into(imageView);
}
当占位图的ScaleType和图片的ScaleType不一致时,占位图和图片就会有一个ScaleType不对,怎么解决呢,我这边是通过listener巧妙的解决了这个问题,代码如下:
public static void display(ImageView imageView, String url) {
Glide.with(imageView.getContext()).load(url)
.listener(new SGlideRequestListener(imageView, ImageView.ScaleType.FIT_XY, ImageView.ScaleType.CENTER_CROP))
.transition(new DrawableTransitionOptions().crossFade())
.into(imageView);
}
static class SGlideRequestListener implements RequestListener<String, GlideDrawable> {
private ImageView.ScaleType mPlaceScaleType;
private ImageView.ScaleType mActualScaleType;
private ImageView mImageView;
SGlideRequestListener(ImageView mImageView, ImageView.ScaleType placeScaleType, ImageView.ScaleType actualScaleType){
this.mPlaceScaleType = placeScaleType;
this.mActualScaleType = actualScaleType;
this.mImageView = mImageView;
mImageView.setScaleType(placeScaleType);
}
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
mImageView.setScaleType(mPlaceScaleType);
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
mImageView.setScaleType(mActualScaleType);
return false;
}
}
当需要提前预下载好图片, 可以使用preload()方法
public static void preloadImage(String url) {
if (TextUtils.isEmpty(url)) {
return;
}
Glide.with(SSTApplication.getContext())
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.preload();
}
当需要通过url获取缓存文件对象时
private static File getCachedFile(String url) {
if (TextUtils.isEmpty(url)) {
return null;
}
File localFile = DiskLruCacheWrapper.get(Glide.getPhotoCacheDir(SSTApplication.getContext()),
DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE).get(new OriginalKey(url, EmptySignature.obtain()));
Logger.d(TAG,localFile!=null?localFile.getAbsolutePath():"null");
return localFile;
}
static class OriginalKey implements Key {
private final String id;
private final Key signature;
private OriginalKey(String id, Key signature) {
this.id = id;
this.signature = signature;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
OriginalKey that = (OriginalKey) o;
return id.equals(that.id) && signature.equals(that.signature);
}
@Override
public int hashCode() {
int result = id.hashCode();
result = 31 * result + signature.hashCode();
return result;
}
@Override
public void updateDiskCacheKey(MessageDigest messageDigest) throws UnsupportedEncodingException {
messageDigest.update(id.getBytes(STRING_CHARSET_NAME));
signature.updateDiskCacheKey(messageDigest);
}
}
根据url判断图片是否下载
File localFile = DiskLruCacheWrapper.get(Glide.getPhotoCacheDir(SSTApplication.getContext()),
DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE).get(new OriginalKey(url, EmptySignature.obtain()));
return localFile!=null;
清除当前url的缓存
File localFile = DiskLruCacheWrapper.get(Glide.getPhotoCacheDir(SSTApplication.getContext()),
DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE).get(new OriginalKey(url, EmptySignature.obtain()));
if(file != null)
file.delete();
通过自定义View实现Fresco的viewAspectRatio
宽高比功能
public class SImageView extends AppCompatImageView {
private float mAspectRatio = 0;
public SImageView(Context context) {
this(context,null);
}
public SImageView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public SImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
private void init(AttributeSet attrs) {
final TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.SImageView);
if(typedArray != null) {
if (typedArray.hasValue(R.styleable.SImageView_viewAspectRatio)) {
mAspectRatio = typedArray.getFloat(R.styleable.SImageView_viewAspectRatio,0);
}
typedArray.recycle();
}
}
public void setAspectRatio(float aspectRatio){
if(mAspectRatio != 0) {
mAspectRatio = aspectRatio;
requestLayout();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(mAspectRatio != 0) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = (int) (width / mAspectRatio);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
attrs.xml
<declare-styleable name="SImageView">
<attr name="viewAspectRatio" format="float"/>
</declare-styleable>
布局文件中只要在SImageView设置app:viewAspectRatio
属性即可,
如:
<com.soaic.widget.SImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:viewAspectRatio="2" />
OK, 以上就是我在项目中遇到的一些坑及解决方法,希望对大家有所帮助!