原文:https://github.com/bumptech/glide/wiki
参考:http://blog.csdn.net/fandong12388/article/details/46372255
Glide作者的GitHub地址:https://github.com/bumptech/glide
jar下载地址:https://github.com/bumptech/glide/releases
Glide和Picasso对比介绍:http://blog.csdn.net/cym492224103/article/details/45055341
Glide 简单示例:http://blog.csdn.net/zhangphil/article/details/45535693
Glide.with(context).load(...).asBitmap() //显示gif静态图片
Glide.with(context).load(...).asGif() //显示gif动态图片
Glide现在还可以把视频解码为一张图片:
Glide.with(context).load(“视频路径“)
(经过我的测试,只能把手机本地的mp4视频解析为一张图片,把mp4文件放在raw文件中,不能解析)
//加载yourView1/10尺寸的缩略图,然后加载全图
Glide.with(yourFragment).load(yourUrl).thumbnail(0.1f).into(yourView)
同时将Activity/Fragment作为with()参数的好处是:图片加载会和Activity/Fragment的生命周期保持一致,
Glide的.toBytes()和.transcode()方法允许在后台获取、解码和转换一个图片,你可以将一张图片转换成更多有用的图片格式,比如,上传一张250*250的图片
Glide.with(context)
.load(“/user/profile/photo/path”)
.asBitmap()
.toBytes()
.centerCrop()
.into(new SimpleTarget<byte[]>(250, 250) {
@Override
public void onResourceReady(byte[] data, GlideAnimation anim) {
// Post your bytes to a background thread and upload them here.
}
});
比如
(.animate(ViewPropertyAnimation.Animator)),
You can now choose to use either OkHttp, or Volley, or Glide’s HttpUrlConnection default as your network stack.
Volley和OkHttp可以在gradle文件当中添加依赖,注册相应的ModelLoaderFactory
图片缓存的键值主要用于DiskCacheStrategy.RESULT,Glide当中的键值主要包含三个部分:
通过DataFetcher.getId()方法返回的String数据作为键值。一般的DataFetchers会简单返回数据模型data model的toString()结果,如果是URL/File会返回相应的路径
图片的尺寸,主要是通过override(width,height)或者通过Target’s getSize()方法确定的尺寸信息
包含一个可选的签名所有的这些东西会通过一种散列算法生成一个独有、安全的文件名,通过此文件名将图片缓存在disk中
因为Glide当中图片缓存key的生成是通过一个散列算法来实现的,所以很难手动去确定哪些文件可以从缓存当中进行删除
2.1 当内容(url,file path)改变的时候,改变相应的标识符就可以了,Glide当中也提供了signature()方法,将一个附加的数据加入到缓存key当中
Glide.with(yourFragment)
.load(yourFileDataModel)
.signature(new StringSignature(yourVersionMetadata))
.into(yourImageView);
Glide.with(fragment)
.load(mediaStoreUri) .signature(new MediaStoreSignature(mimeType, dateModified, orientation)) .into(view);
自定义标识符
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;
}
@Override
public void updateDiskCacheKey(MessageDigest md) {
messageDigest.update(ByteBuffer.allocate(Integer.SIZE)
.putInt(signature).array());
}
}
2.2、不缓存可以通过diskCacheStrategy(DiskCacheStrategy.NONE.)实现
可以通过GlideModule接口来配置Glide的配置文件,并且像ModelLoaders一样注册相关组件。
1.包含一个GlideMode
第一步、To use and register a GlideModule, first implement the interface with your configuration and components:
public class MyGlideModule implements GlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
// Apply options to the builder here.
}
@Override
public void registerComponents(Context context, Glide glide) {
// register ModelLoaders here.
}
}
第二步、然后将上面的实现了加入到proguard.cfg当中:
-keepnames class * com.mypackage.MyGlideModule
第三步、在AndroidManifest.xml文件中添加meta-data,以便Glide能够找到你的Module
<meta-data
android:name="com.example.xx.glide"
android:value="MyGlideModule " />
一个Library项目可能会定义一个或者多个GlideModules,如果一个Library项目添加一个Module到Library项目的manifest当中,依赖于此Library的应用就会自动加载依赖库(Library项目)当中的Module。
当然,如果manifest的合并不正确,那么Library里面Module就必须手动地在应用当中添加进去
虽然Glide允许一个应用当中存在多个GlideModules,Glide并不会按照一个特殊的顺序去调用已注册的GlideModules,如果一个应用的多个依赖工程当中有多个相同的Modules,就有可能会产生冲突。
如果一个冲突是不可避免的,应用应该默认去定义一个自己的Module,用来手动地处理这个冲突,在进行Manifest合并的时候,可以用下面的标签排除冲突的module
<meta-data android:name="com.example.xx.glide" tools:node="remove"/>
Glide允许开发者配置自定义的全局操作应用于所有的请求,这个部分可以通过GlideModule接口中的applyOptions方法的GlideBuilder参数实现 :
1.1、硬盘缓存是在一个后台线程当中,通过一个DiskCache.Factory接口进行缓存的。
1.2.设置disk缓存的大小 : InternalCacheDiskCacheFactory
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, yourSizeInBytes));
1.3.设置缓存的路径
可以通过实现DiskCache.Factory,然后使用DiskLruCacheWrapper创建一个新的缓存目录,比如,可以通过如下方式在外存当中创建缓存目录:
builder .setDiskCache(new DiskCache.Factory() {
@Override
public DiskCache build() {
// Careful: the external cache directory doesn't enforce permissions
File cacheLocation = new File(context.getExternalCacheDir(), "cache_dir_name");
cacheLocation.mkdirs();
return DiskLruCacheWrapper.get(cacheLocation, yourSizeInBytes);
}
});
GlideBuilder当中,允许开发者去设置内存当中图片缓存区的大小,主要涉及到的类包括MemoryCache和BitmapPool
2.1 大小的设置
默认内存缓存的大小是用过MemorySizeCalculator来实现的,这个类会根据设备屏幕的大小,计算出一个合适的size,开发者可以获取到相关的默认设置信息:
MemorySizeCalculator calculator = new MemorySizeCalculator(context);
int defaultMemoryCacheSize = calculator.getMemoryCacheSize();
int defaultBitmapPoolSize = calculator.getBitmapPoolSize();
如果在应用当中想要调整内存缓存的大小,开发者可以通过如下方式:
Glide.get(context).setMemoryCategory(MemoryCategory.HIGH);
2.2 Memory Cache
Glide内存缓存的目的是减少I/O,提高效率
可以通过GlideBuidler的setMemoryCache(MemoryCache memoryCache)去设置缓存的大小,开发者可以通过LruResourceCache类去设置缓存区的大小
builder.setMemoryCache(new LruResourceCache(yourSizeInBytes));
2.3 Bitmap Pool
可以通过GlideBuilder的setBitmapPool()方法设置池子的大小,LruBitmapPool是Glide的默认实现,使用如下:
builder.setBitmapPool(new LruBitmapPool(sizeInBytes));
GlideBuilder允许开发者设置一个全局的默认图片格式,
在默认情况下,Glide使用RGB_565格式加载图片,如果想要使用高质量的图片,可以通过如下方式设置系统的图片格式:
builder.setDecodeFormat(DecodeFormat.ALWAYS_ARGB_8888);
除了可以将图片、视频快照和GIFS显示在View上面之外,开发者也可以在自定义的Target上面显示这些媒体文件
重点内容
onResourceReady(R resource,GlideAnimation<? super R> glideAnimation)
int myWidth = 512;
int myHeight = 384;
Glide.with(yourApplicationContext))
.load(youUrl)
.asBitmap()
.into(new SimpleTarget<Bitmap>(myWidth, myHeight) {
@Override
public void onResourceReady(Bitmap bitmap, GlideAnimation anim) {
// Do something with bitmap here.
}
};
说明:
如果你想加载一张图片到一个view当中,但是又想改变或者监听Glide默认的部分设置,就可以通过重写ViewTarget或者他的子类来实现
如果你想Gidle加载图片的时候可以自定义图片的大小,或者想要设置一个自定义的显示动画,就可以通过ViewTarget来实现,可以通过一个静态的ViewTarget或者动态的内部类来实现相关的功能
Glide.with(yourFragment)
.load(yourUrl) .into(new ViewTarget<YourViewClass, GlideDrawable>(yourViewObject) { @Override public void onResourceReady(GlideDrawable resource, GlideAnimation anim) { YourViewClass myView = this.view;
// Set your resource on myView and/or start your animation here. } });
说明:
如果只是想使用Glide的默认配置,可以使用Glide当中ImageViewTargets的两个子类:
Glide.with(yourFragment)
.load(yourUrl)
.asBitmap()
.into(new BitmapImageViewTarget(yourImageView)) {
@Override
public void onResourceReady(Bitmap bitmap, GlideAnimation anim) {
super.onResourceReady(bitmap, anim);
Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
// Here's your generated palette
}
});
}
});
Glide的ModelLoader接口为开发者提供了装载图片的view的尺寸,并且允许开发者使用这些尺寸信息去选择合适的URL去下载图片。选用适当的尺寸可以节省宽带和设备的空间开销,提高app的性能
2014年googleI/o大会发表了一篇文章,阐述了他们如何使用ModelLoader接口去适配图片的尺寸,见下面的连接:https://github.com/google/iosched/blob/master/doc/IMAGES.md
1、通过http/https下载图片,可以通过继承BaseGlideUtlLoader来实现:
public interface MyDataModel {
public String buildUrl(int width, int height);
}
public class MyUrlLoader extends BaseGlideUrlLoader<MyDataModel> {
@Override
protected String getUrl(MyDataModel model, int width, int height) {
// Construct the url for the correct size here.
return model.buildUrl(width, height);
}
}
2、可以使用你自定义的ModelLoader去加载图片了
Glide.with(yourFragment)
.using(new MyUrlLoader())
.load(yourModel)
.into(yourView);
如果你想避免每次加载图片都要使用.using(new MyUrlLoader()) ,可以实现是一个
ModelLoaderFactory然后使用Glide将它注册到GlideModule当中
public class MyGlideModule implements GlideModule {
...
@Override
public void registerComponents(Context context, Glide glide) {
glide.register(MyDataModel.class, InputStream.class,
new MyUrlLoader.Factory());
}
}
这样你就可以跳过.using()了
Glide.with(yourFragment)
.load(yourModel) .into(yourView);
Glide包含一些小的、可选的集成库,目前Glide集成库当中包含了访问网络操作的Volley和OkHttp
这些集成库,和Glide的ModelLoader系统允许开发者使用一致地框架去进行网络相关的操作
将一个库集成到Glide当中需要两步操作,
第一步、添加依赖
dependencies { compile 'com.github.bumptech.glide:volley-integration:1.2.2' compile 'com.mcxiaoke.volley:library:1.0.5' }
第二步、创建Volley集成库的GlideModule
<meta-data
android:name="com.bumptech.glide.integration.volley.VolleyGlideModule"
android:value="GlideModule" />
然后改变混淆文件:
-keep class com.bumptech.glide.integration.volley.VolleyGlideModule
#or
-keep public class * implements com.bumptech.glide.module.GlideModule
第一步、添加依赖
dependencies { compile 'com.github.bumptech.glide:okhttp-integration:1.2.2' compile 'com.squareup.okhttp:okhttp:2.0.0' }
第二步、创建OkHttp集成库的GlideModule
<meta-data
android:name="com.bumptech.glide.integration.okhttp.OkHttpGlideModule"
android:value="GlideModule" />
-keep class com.bumptech.glide.integration.okhttp.OkHttpGlideModule
#or
-keep public class * implements com.bumptech.glide.module.GlideModule
为了保证Glide在后台线程当中加载资源文件更加容易,Glide除了Glide.with(fragment).load(url).into(view)之外还提供了
downloadOnly(int width, int height) downloadOnly(Y target)// Y extends Target<File> into(int width, int height)
Glide的downloadOnly()允许开发者将Image的二进制文件下载到硬盘缓存当中,以便在后续使用,
1、 在后台线程当中下载图片,可以通过如下的方式:
FutureTarget<File> future = Glide.with(applicationContext)
.load(yourUrl)
.downloadOnly(500, 500);
File cacheFile = future.get();
当future返回的时候,image的二进制文件信息就存入了disk缓存了,值得注意的是downloadOnly API只是保证图片个bytes数据在disk当中是有效的。
2、下载完毕之后如果想要进行显示,可以通过如下方式进行调用:
Glide.with(yourFragment)
.load(yourUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(yourView);
Glide.with(yourFragment)
.load(yourUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(yourView);
通过DiskCacheStrategy.ALL或者DiskCacheStrategy.SOURCE,可以保证程序会去读取缓存文件
不通过downloadOnly,可以使用into(),会返回一个FutureTarget对象,比如,想要得到一个URL对应的500*500的centerCrop裁剪图片,可以通过如下方式实现:
Bitmap myBitmap = Glide.with(applicationContext)
.load(yourUrl)
.asBitmap()
.centerCrop()
.into(500, 500)
.get()
注意:上面的调用只能在异步线程当中,如果在main Thread当中调用.get(),会阻塞主线
Glide两个默认的转换器,fitCenter和CenterCrop,其他的转换器详见https://github.com/wasabeef/glide-transformations,可以将图片转为各种形状,例如圆形,圆角型等等
用法:
Glide.with(yourFragment)
.load(yourUrl)
.fitCenter()
.into(yourView);
Glide.with(yourFragment)
.load(yourUrl)
.centerCrop()
.into(yourView);
// For Bitmaps:
Glide.with(yourFragment)
.load(yourUrl)
.asBitmap()
.centerCrop()
.into(yourView);
// For gifs:
Glide.with(yourFragment)
.load(yourUrl)
.asGif()
.fitCenter()
.into(yourView);
甚至可以在两幅图片进行类型转换的时候进行transformed
Glide.with(yourFragment)
.load(yourUrl)
.asBitmap()
.toBytes()
.centerCrop()
.into(new SimpleTarget<byte[]>(...) { ... });
方法:
第一步、编写转换器类 ,继承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 = ... // apply some transformation here.
return myTransformedBitmap;
}
@Override
public String getId() {
// Return some id that uniquely identifies your transformation.
return "com.example.myapp.MyTransformation";
}
}
第二步、在Glide方法链当中用.transform(…)替换fitCenter()/centerCrop()
Glide.with(yourFragment)
.load(yourUrl)
.transform(new MyTransformation(context))
.into(yourView);
// For Bitmaps:
Glide.with(yourFragment)
.load(yourUrl)
.asBitmap()
.transform(new MyTransformation(context))
.into(yourView);
// For Gifs:
Glide.with(yourFragment)
.load(yourUrl)
.asGif()
.transform(new MyTransformation(context))
.into(yourView);
在上面使用过程当中没有设置尺寸值,那么转换器转换的图片尺寸怎么确定呢,
为了减少垃圾收集,可以通过BitmapPool接口去释放不需要的Bitmaps,当然也可以对里面的bitmap进行再利用。
例如在一次转换中,
4.1 不要手动地去释放一个转换的bitmap资源,也不要将transform()之后的Bitmap重新放置到BitmapPool当中去
protected Bitmap transform(BitmapPool bitmapPool, Bitmap original, int width, int height) {
Bitmap result = bitmapPool.get(width, height, Bitmap.Config.ARGB_8888);
// If no matching Bitmap is in the pool, get will return null, so we should //allocate.
if (result == null) {
// Use ARGB_8888 since we're going to add alpha to the image.
result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
}
// Create a Canvas backed by the result Bitmap.
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setAlpha(128);
// Draw the original Bitmap onto the result Bitmap with a transformation.
canvas.drawBitmap(original, 0, 0, paint);
// Since we've replaced our original Bitmap, we return our new Bitmap here. Glide will
// will take care of returning our original Bitmap to the BitmapPool for us.
return result;
}