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 + ")";
}

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容