glide 个人使用记录总结

1.glide引用相关配置

在app下的build.gradle中添加依赖:

   compile 'com.github.bumptech.glide:glide:3.7.0'

混淆配置规则

 # 表示不混淆所有glideModule
    -keep public class * implements com.bumptech.glide.module.GlideModule
    -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
    **[] $VALUES;
    public *;
  }

如果项目中集成网络框架OkHttp我们就需要配置一下防止混淆规则,okhttp具有支持HTTP/2、利用连接池技术减少请求延迟、缓存响应结果等等优点,需要在混淆文件里面添加一下配置

  -keep class com.bumptech.glide.integration.okhttp.OkHttpGlideModule

2.glide的使用

  • 简单使用
   Glide.with(this).load(url).into(imageView);
glide不同资源的加载方式,理论上Glide基本可以load任何可以拿到的媒体资源
    load SD卡资源:load("file://"+ Environment.getExternalStorageDirectory().getPath()+"/test.jpg”)

load assets资源:load("file:///android_asset/test.gif”)

load raw资源:load("Android.resource://com.abc.glide/raw/raw_1”)
或load("android.resource://com.abc.glide/raw/"+R.raw.raw_1)

load drawable资源:load("android.resource://com.abc.glide/drawable/test”)
或load("android.resource://com.abc.glide/drawable/"+R.drawable.test)

load ContentProvider资源:load("content://media/external/images/media/123456”)
load http 资源:load("http://img.abc.com/201701/05/123456789_1122.jpg")  

//glide默认支持webp图片,使加载图片响应速度更快
load https资源:load("https://img.abc.com/XXXXXXXXXX-48076-560.jpg_240x5000q50.jpg_.webp")
  • Glide.with()使用
    with(Context context). 使用Application作为上下文,Glide请求将不受Activity/Fragment生命
    周期控制
    with(Activity activity).使用Activity作为上下文,Glide的请求会受到Activity生命周期控制
    with(FragmentActivity activity).Glide的请求会受到FragmentActivity生命周期控制
    with(android.app.Fragment fragment).Glide的请求会受到Fragment 生命周期控制。
    with(android.support.v4.app.Fragment fragment).Glide的请求会受到Fragment生命周期控

    返回关联了对应上下文的RequestManager实例

  • GenericRequestBuilder使用
    1.dontAnimate() 移除所有的动画

    2.diskCacheStrategy(DiskCacheStrategy strategy) 设置缓存策略。
    DiskCacheStrategy.SOURCE:缓存原始数据,DiskCacheStrategy.RESULT:缓存变换(如
    缩放、裁剪等)后的资源数据
    DiskCacheStrategy.NONE:什么都不缓存
    DiskCacheStrategy.ALL:缓存SOURC和RESULT
    默认采用DiskCacheStrategy.RESULT策略,对于download only操作要使用
    DiskCacheStrategy.SOURCE

    3.placeholder(int resourceId)/placeholder(Drawable drawable) 设置资源加载过程中的占
    位Drawable id/Drawable。

    4.fallback(int resourceId)/fallback(Drawable drawable) 设置model为空时要显示的
    Drawable id/Drawable。如果没有设置fallback,model为空时将显示error的Drawable,如果
    error的Drawable也没设置,就显示placeholder的Drawable

    5.error(int resourceId)/error(Drawable drawable) 设置load失败时显示的Drawable
    id/Drawable

    6.animate(int animationId)/animate(ViewPropertyAnimation.Animator animator) 在异步加
    载资源完成时会执行该动画

    7.preload(int width, int height) 预加载resource到缓存中(单位为pixel)

    8.thumbnail(float sizeMultiplier 请求给定系数的缩略图。如果缩略图比全尺寸图先加载
    完,就显示缩略图,否则就不显示。系数sizeMultiplier必须在(0,1)之间,可以递归调用该方
    法。

    9.sizeMultiplier(float sizeMultiplier) 在加载资源之前给Target大小设置系数

    10.priority(Priority priority) 指定加载的优先级,优先级越高越优先加载,但不保证所有图
    片都按序加载。枚举Priority.IMMEDIATE,Priority.HIGH,Priority.NORMAL,
    Priority.LOW。默认为Priority.NORMAL

    11.asBitmap() 无论资源是不是gif动画,都作为Bitmap对待。如果是gif动画会停在第一帧

    12.asGif() 把资源作为GifDrawable对待。如果资源不是gif动画将会失败,会回调.error()

    13.skipMemoryCache(boolean skip) 设置是否跳过内存缓存,但不保证一定不被缓存(比
    如请求已经在加载资源且没设置跳过内存缓存,这个资源就会被缓存在内存中)

    14.override(int width, int height) 重新设置Target的宽高值(单位为pixel)

    15.into(Y target) 设置资源将被加载到的Target

    16.into(ImageView view) 设置资源将被加载到的ImageView。取消该ImageView之前所有的加载并释放资源

    17.into(int width, int height) 后台线程加载时要加载资源的宽高值(单位为pixel)

    18.listener(RequestListener<? super ModelType, TranscodeType> requestListener) 监听资源加载的请求状态,可以使用两个回调:onResourceReady(R resource, T model, Target<R> target, boolean isFromMemoryCache, boolean isFirstResource)和onException(Exception e, T model, Target<R> target, boolean isFirstResource),但不要每次请求都使用新的监听器,要避免不必要的内存申请,可以使用单例进行统一的异常监听和处理。

3.glide缓存设置攻略

1.禁止内存缓存

     .skipMemoryCache(true)
    ```
2.禁止磁盘缓存

.diskCacheStrategy(DiskCacheStrategy.NONE)
```

3.清除内存缓存

    // 必须在UI线程中调用
    Glide.get(context).clearMemory();
   ```
   
4.清除磁盘缓存

// 必须在后台线程中调用,建议同时clearMemory()
Glide.get(applicationContext).clearDiskCache();
```

5.让缓存根据版本过期清理

     .signature(new StringSignature(context))     //通过版本使缓存失效,有时我们并不是想要清理所有缓存,
        //  只是app版本变动则原来的缓存可能不需要了,或本地图片库中图片变更但是文件名地址没有变则可能就出现继
        // 续使用原来的缩略图其实最好的情况是如果数据变更则相应的改变url,如果不改变可以使用StringSignature解决
        //  这个问题
    ```

   6.设置缓存路径的两种方式

 /**
 * 设置磁盘缓存大小和位置,这里设置150M
 */
public static void setInnerCacheDir(Context context){
    GlideBuilder builder = new GlideBuilder(context);
    builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "ImgCache", 150 * 1024 * 1024));
}

/**
 * 可以用ExternalCacheDiskCacheFactory来把你的磁盘缓存放到sd卡的公共缓存目录上,这里默认设置150M
 */
public static void setDiskCacheDir(Context context){
    GlideBuilder builder = new GlideBuilder(context);
    builder.setDiskCache( new ExternalCacheDiskCacheFactory(context, ImgCache", 150 * 1024 * 1024));
}

7.我们也可以通过配置一个glideModule来做相关的缓存配置

public class GlideConfiguration implements GlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
//自定义缓存目录,磁盘缓存给150M 另外一种设置缓存方式
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, “ImgCache”, 150 * 1024 * 1024));
//配置图片缓存格式 默认格式为565
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
//另一种缓存策略方式
// builder.setDiskCache(new DiskLruCacheFactory(dirPath, DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE));
}

@Override
public void registerComponents(Context context, Glide glide) {

}

}


# 4.获取缓存大小

/**
* 获取缓存在磁盘上的图片大小
*/
public static void getCacheSize(Context context){
GlideBuilder builder = new GlideBuilder(context);
new GetDiskCacheSizeTask().execute(new File(context.getCacheDir(),
DiskCache.Factory.DEFAULT_DISK_CACHE_DIR));
}

static class GetDiskCacheSizeTask extends AsyncTask<File, Long, Long> {

// private final TextView resultView;

    public GetDiskCacheSizeTask() {
    }

    @Override
    protected void onPreExecute() {

// resultView.setText(“Calculating…”);
}

    @Override
    protected void onProgressUpdate(Long... values) { /* onPostExecute(values[values.length - 1]); */ }

    @Override
    protected Long doInBackground(File... dirs) {
        try {
            long totalSize = 0;
            for (File dir : dirs) {
                publishProgress(totalSize);
                totalSize += calculateSize(dir);
            }
            return totalSize;
        } catch (RuntimeException ex) {
            final String message = String.format("Cannot get size of %s: %s", Arrays.toString(dirs), ex);
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {

// resultView.setText(“error”);
Toast.makeText(FanhuanApplication.getInstance().getApplication(), message, Toast.LENGTH_LONG).show();
}
});
}
return 0L;
}

    @Override
    protected void onPostExecute(Long size) {
        String sizeText = android.text.format.Formatter.formatFileSize(FanhuanApplication.getInstance().getApplication(), size);

// resultView.setText(sizeText);
Logger.e(“filePath:sizeText:” + sizeText);
}

    private static long calculateSize(File dir) {
        if (dir == null) return 0;
        if (!dir.isDirectory()) return dir.length();
        long result = 0;
        File[] children = dir.listFiles();
        if (children != null)
            for (File child : children)
                result += calculateSize(child);
        return result;
    }
}

# 5.设置图片加载监听

//设置错误监听
static RequestListener<String,GlideDrawable> errorListener=new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {

        Log.e("onException",e.toString()+"  model:"+model+" isFirstResource: "+isFirstResource);

// imageView.setImageResource(R.mipmap.ic_launcher);
// onResourceReady: isFromMemoryCache:false 首次从网络第一次加载url
// onResourceReady: isFromMemoryCache:true 第二次从缓存加载
// onException: java.net.UnknownHostException:无网络exception
// onException: java.io.FileNotFoundException 错误的url(非图片类型url)
// onException: java.io.IOException 错误的url
return false;
}

    @Override
    public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
        Log.e("onResourceReady","isFromMemoryCache:"+isFromMemoryCache+"  model:"+model+" isFirstResource: "+isFirstResource);
        return false;
    }
} ;

# 6.glide加载gif图片的几种方式

    1.Glide.with(context).load(url).asGif().into(imageView);
        注意:如果加载的图片不是gif,则asGif()会报错, 如果图片不一定是gif图,asGif()不写
        也是可以正常加载
    2.gif图加载控制
    默认的加载方式是循环播放的gif图的,有的时候我们需要控制动画的播放次数,而Glide也没有开放单独的api接口用来控制gif播放次数,这时可以通过GlideDrawableImageViewTarget(ImageView view, int maxLoopCount)来实现, 其中第二个参数表示播放的次数:

    ```
     Glide.with(context).load(url).into(new GlideDrawableImageViewTarget(imageView, 1));
    ```

    3.监听播放状态,就需要添加一个RequestListener

    ```
     Glide.with(context).load(url).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) {

                Observable.just(resource)
                        .flatMap(new Func1<GlideDrawable, Observable<?>>() {
                            @Override
                            public Observable<?> call(GlideDrawable glideDrawable) {
                                int duration = 0;
                                try {
                                    GifDrawable gifDrawable = (GifDrawable) glideDrawable;
                                    GifDecoder decoder = gifDrawable.getDecoder();
                                    for (int i = 0; i < gifDrawable.getFrameCount(); i++) {
                                        duration += decoder.getDelay(i);                            }
                                } catch (Throwable e) {
                                }
                                return Observable.just(null).delay(duration, TimeUnit.MILLISECONDS);
                            }
                        })
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribeOn(Schedulers.io())
                        .subscribe(new Action1<Object>() {
                            @Override
                            public void call(Object o) {
                                // 加载完成后的操作
                            }
                        });

                return false;
            }
        })
        .into(new GlideDrawableImageViewTarget(imageView, 1));
    ```

# 7.对图片进行裁剪、滤镜、模糊等处理:    

 图片处理推荐使用第三方库https://github.com/wasabeef/glide-transformations
    接下来我们就可以用这个库里面的一些方法对图片进行一下操作,以下是部分使用方法,更多的方法可以自己去体验

//圆形裁剪
Glide.with(context).load(url).bitmapTransform(new CropCircleTransformation(context)).into(imageView);
//圆角处理
Glide.with(context).load(url).bitmapTransform(new RoundedCornersTransformation(context,30,0,     
RoundedCornersTransformation.CornerType.ALL)).into(imageView);
//灰度处理
Glide.with(context).load(url).bitmapTransform(new GrayscaleTransformation(context)).into(imageView);

如果想自己定义Transformation,最简单的方式就是直接继承BitmapTransformation:

 private static class MyTransformation extends BitmapTransformation {

public MyTransformation(Context context) {
    super(context);
}

@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform,
        int outWidth, int outHeight) {
   Bitmap myTransformedBitmap = ... //对Bitmap进行各种变换处理
   return myTransformedBitmap;
}

@Override
public String getId() {
    // 返回代表该变换的唯一Id,会作为cache key的一部分。
    // 注意:最好不要用getClass().getName(),因为容易受混淆影响。如果变换过程不影响缓存数据,可以返回空字符串。
    return "com.example.MyTransformation";
}

}


  使用方法:

Glide.with(context).load(url).asBitmap().transform(new MyTransformation(context)).into(view);


自定义图片处理时Glide会自动计算View/Target大小,我们不需要传View的宽高,当然你可以使用override(int, int)去        
    改变这种行为。

自定义图片处理时,为了避免创建大量Bitmap以及减少GC,可以考虑重用Bitmap,这就需要BitmapPool,典型地就    
    是,从Bitmap池中拿一个Bitmap,用这个Bitmap生成一个Canvas, 然后在这个Canvas上画初始的Bitmap并使用
    Matrix、Paint、或者Shader处理这张图片。为了有效并正确重用Bitmap需要遵循以下三条准则:

1.永远不要把transform()传给你的原始resource或原始Bitmap给recycle()了,更不要放回BitmapPool,因为这些都自    
    动完成了。值得注意的是,任何从BitmapPool取出的用于自定义图片变换的辅助Bitmap,如果不经过transform()方法    
    返回,就必须主动放回BitmapPool或者调用recycle()回收。
    2.如果你从BitmapPool拿出多个Bitmap或不使用你从BitmapPool拿出的一个Bitmap,一定要返回extras给    
    BitmapPool。
    3.如果你的图片处理没有替换原始resource(例如由于一张图片已经匹配了你想要的尺寸,你需要提前返回),     
    transform()`方法就返回原始resource或原始Bitmap。

示例如下:

private static class MyTransformation extends BitmapTransformation {

    public MyTransformation(Context context) {
        super(context);
    }

    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        Bitmap result = pool.get(outWidth, outHeight, Bitmap.Config.ARGB_8888);
        // 如果BitmapPool中找不到符合该条件的Bitmap,get()方法会返回null,就需要我们自己创建Bitmap了
        if (result == null) {
            // 如果想让Bitmap支持透明度,就需要使用ARGB_8888
            result = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888);
        }
        //创建最终Bitmap的Canvas.
        Canvas canvas = new Canvas(result);
        Paint paint = new Paint();
        paint.setAlpha(128);
        // 将原始Bitmap处理后画到最终Bitmap中
        canvas.drawBitmap(toTransform, 0, 0, paint);
        // 由于我们的图片处理替换了原始Bitmap,就return我们新的Bitmap就行。
        // Glide会自动帮我们回收原始Bitmap。
        return result;
    }

    @Override
    public String getId() {
        // Return some id that uniquely identifies your transformation.
        return "com.example.myapp.MyTransformation";
    }
}

 也可以直接实现Transformation接口,进行更灵活的图片处理,如进行简单地圆角处理:

public class RoundedCornersTransformation implements Transformation<Bitmap> {

private BitmapPool mBitmapPool;
private int mRadius;

public RoundedCornersTransformation(Context context, int mRadius) {
    this(Glide.get(context).getBitmapPool(), mRadius);
}

public RoundedCornersTransformation(BitmapPool mBitmapPool, int mRadius) {
    this.mBitmapPool = mBitmapPool;
    this.mRadius = mRadius;
}

@Override
public Resource<Bitmap> transform(Resource<Bitmap> resource, int outWidth, int outHeight) {
    //从其包装类中拿出Bitmap
    Bitmap source = resource.get();
    int width = source.getWidth();
    int height = source.getHeight();
    Bitmap result = mBitmapPool.get(width, height, Bitmap.Config.ARGB_8888);
    if (result == null) {
        result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    }
    Canvas canvas = new Canvas(result);
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
    canvas.drawRoundRect(new RectF(0, 0, width, height), mRadius, mRadius, paint);
    //返回包装成Resource的最终Bitmap
    return BitmapResource.obtain(result, mBitmapPool);
}

@Override
public String getId() {
    return "RoundedTransformation(radius=" + mRadius + ")";
}

}

    原文作者:听话哥
    原文地址: https://www.jianshu.com/p/53af08d91c00
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞