Glide框架学习总结

来源:互联网 发布:h3c mac认证 编辑:程序博客网 时间:2024/04/28 23:32

·背景

之前出于兴趣,做了一个阅读资讯类的app(github地址:Github-More),图片加载框架采用的是Glide,觉得用起来特别方便,而且效果也很不错,后来看到了郭霖大神的博客有对Glide框架的解析(郭霖的博客对Glide框架分成了几个部分写,而且可能还在连载中,有兴趣可以搜一下郭霖的博客),内容比较多,研读了几天,并且也查阅相关资料,同时也做了一些实践,打算写一篇自己近期对Glide的一个总结。

·Glide简介

Glide是当下比较流行的一个图片加载库,与其有相似功能的还有:Volley,Picasso,Fresco。相比之下,这些框架有以下各自的特点:
  • Volley 单线程,而且不支持本地图片加载
  • 另外三个框架的功能都比较相似,相对而言,Picasso和Glide的用法相对比较简单。具体的比较可以参考这篇Blog:比较Picasso、Glide 和 Fresco 三种图片加载库

More是基于一个开源项目改的,原项目采用的是Volley的图片加载框架,而我采用的则是Glide框架。因此接下来我将简述一下Glide框架的一些特性。

首先是Glide的用法,Glide的用法特别简单,一句话就完成了图片加载代码:
Glide.with(this).load(url).into(imageView);
其中,.with()方法是创建一个加载图片的实例,.load()负责加载网络或本地资源,into()则是将图片资源显示到对应的控件中。
接下来对Glide的几个常用方法进行简单解释。

with()方法

with()方法可以传入一个Context,Activity,或者是Fragment,如果为了简单,可以直接传入this。万一如果调用的地方不在Activity或者Fragment中,我们可以获取当前应用程序的ApplicationContext,并传如到with()方法中。
该方法主要是决定了Glide加载图片的生命周期,将Glide加载图片与传入的参数同步生命周期。如果传入的参数是ApplicationContext,那么只有当应用程序被kill时候,图片加载才会停止。

load()方法

load()方法主要是加载资源,资源可以是本地资源,或者是网络资源,二进制流。

into()方法

into()方法负责将图片显示到哪个控件(ImageView)上。

除此之外,关于Glide。我还常用到一些方法。


placeholder()占位图

当图片加载时,显示一幅占位图


error()异常图

当图片加载失败时,显示一幅异常图


asBitmap()/asGif()

告诉Glide,我想显示的是图片还是动态图。
注:如果载入资源是动态图,而且使用asBitmap()方法,则显示gif的第一帧作为图片;
如果载入资源是静态图,而且使用asGif()方法,则显示加载失败error()。

Glide的缓存机制

缓存功能,主要是通过缓存KEY,在Glide中,生成的KEY所决定的参数比较复杂,在这不阐述了。
Glide的缓存方法主要有两种,一种是内存缓存,一种是硬盘缓存。

内存缓存

内存缓存主要防止应用重复将数据读取到内存中。
Glide是默认启动内存缓存的,当然也可以通过代码将内存缓存功能关闭:
.skipMemoryCache(true)
Glide的内存缓存机制,主要使用了LruCache算法,也就是最近最少使用算法。该算法主要原理如图


将对象存储到LinkedHashMap中,当访问一个对象时候,则将对象存放到Map的最上方,同时清除最底层的Map数据。
这有一个基于android图片加载的Lru算法的实现Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅
关于android采用缓存技术加载图片的方法,可以参考这篇文章:Android高效加载大图、多图解决方案,有效避免程序OOM
同时Glide还采用了一种弱引用的方法,来缓存正在使用的图片,保护这些图片不会被LruCache算法回收掉。

写入缓存的时候,Glide在load网络图片资源的时候,首先将图片缓存在弱引用缓存中(也就是正在使用的图片),当图片不在被使用了,就将图片从弱引用缓存中移除,同时将图片使用LruCache进行缓存。

硬盘缓存

硬盘缓存主要是为了防止应用从网络或其他资源重复下载或者读取数据。
和内存缓存同样的道理,Glide也提供方法设置硬盘缓存的策略:
.diskCacheStrategy(DiskCacheStrategy.NONE)

其中DiskCacheStrategy有4中策略:
  • DiskCacheStrategy.NONE: 表示不缓存任何内容。
  • DiskCacheStrategy.SOURCE: 表示只缓存原始图片。
  • DiskCacheStrategy.RESULT: 表示只缓存转换过后的图片(默认选项)。
  • DiskCacheStrategy.ALL : 表示既缓存原始图片,也缓存转换过后的图片。
硬盘缓存主要也是采用LruCache算法,谷歌也提供了关于硬盘LruCache算法的实现工具类DiskLruCache,同时还有一篇相关文章:Android DiskLruCache完全解析,硬盘缓存的最佳方案
关于取缓存数据:
首先Glide从Cache中找有没有数据,如果没有则从网络中请求资源。DiskCacheStrategy.RESULT和DiskCacheStrategy.SOURCE的区别主要就是,RESULT生成的KEY所决定的参数比较复杂,比如改变图片的width或者height都会改变KEY,而SOURCE的参数泽标简单,主要通过URL来决定。

Glide图片变换

对图片进行变换,也就是说Glide获取到图片资源,在对图片进行展现之前,对图片进行处理,比如模糊化,裁剪等等,使得呈现的效果更炫酷。

在Glide添加图片变换的操作只需添加一个方法即可:
.transform(...)
其中transform()中的操作,Glide提供了两种操作给我们,分别是CenterCrop和FitCenter,当然也可以直接调用Glide的API,
其中,FitCenter是将图片充满全屏,centerCrop是对原图片的中心区域进行裁剪得到的图片。

接下来,我们自定义创建一个图片变换操作。
step1 创建一个继承自BitmapTransformation的类。
public class TesTCrop1 extends BitmapTransformation {    public TesTCrop1(Context context) {        super(context);    } @Override    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {        return null;    }    @Override    public String getId() {        return "com.lilynlee.glidetest.TestCrop1";    }}
step 2 重写transfom方法。
@Override    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {        int diameter = Math.min(toTransform.getWidth(),toTransform.getHeight());        final Bitmap toReuse = pool.get(outWidth,outHeight,Bitmap.Config.ARGB_8888);        final Bitmap result;        if (toReuse != null){            result = toReuse;        }else {            result = Bitmap.createBitmap(diameter,diameter,Bitmap.Config.ARGB_8888);        }        int dx = (toTransform.getWidth()-diameter)/2;        int dy = (toTransform.getHeight()-diameter)/2;        Canvas canvas = new Canvas(result);        Paint paint = new Paint();        BitmapShader shader = new BitmapShader(toTransform, BitmapShader.TileMode.CLAMP,                BitmapShader.TileMode.CLAMP);        if (dx != 0 || dy != 0) {            Matrix matrix = new Matrix();            matrix.setTranslate(-dx, -dy);            shader.setLocalMatrix(matrix);        }        paint.setShader(shader);        paint.setAntiAlias(true);        float radius = diameter / 2f;        canvas.drawCircle(radius, radius, radius, paint);        if (toReuse != null && !pool.put(toReuse)) {            toReuse.recycle();        }        return result;    }
step 3 调用Glide。
Glide.with(this)                .load(url)                .transform(new testCrop(this))                .into(imageView);
网上有很多基于Glide的图片变换开源库,其中典型的就是glide-transformations库,它实现了许多图片的变换效果,比如裁剪,黑白处理,模糊化等操作。
首先将该库加入到项目中,
//Glide的transformation库    compile 'jp.wasabeef:glide-transformations:2.0.2'
如果需要对图片进行模糊处理,则只需要如下图:
Glide.with(this)                .load(url)                .bitmapTransform(new BlurTransformation(this))                .into(imageView);
注意,在这里用的是.bitmapTransform()方法,而不是方法transform()。
也可以两种处理效果的叠加,比如黑白加模糊。
Glide.with(this)                .load(url)                .bitmapTransform(new GrayscaleTransformation(this),new BlurTransformation(this))                .into(imageView);












原创粉丝点击