android 使用Glide
简介
Glide是android快速有效开源的媒体管理和图片加载框架,这个框架包括媒体编码,内存和硬盘缓存,资源池这些简单容易使用的用户接口。
Gilde支持获取,解码展示video,image,动态的gif。Gilide包括一个灵活的API,这些API允许开发者以插件化的方式加入到大多数网络栈中。默认情况下Glide使用自定义的HttpUrlConnection基础栈,但是也包括以插件的方式存在于Google的Volley工程或者Square的OkHttp库的实用工具库。
Glide的主要解决的问题是使加载images的任何类型的可滚动列表尽可能平滑的滚动,但是Glide同时对大多数任何需要获取,重新改变图片尺寸,展示远程图片也非常有效。
怎么使用GIide
最简单的方式是像这样:
// For a simple view:
@Override public void onCreate(Bundle savedInstanceState) {
...
ImageView imageView = (ImageView) findViewById(R.id.my_image_view);
Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);
}
// For a simple image list:
@Override public View getView(int position, View recycled, ViewGroup container) {
final ImageView myImageView;
if (recycled == null) {
myImageView = (ImageView) inflater.inflate(R.layout.my_image_view, container, false);
} else {
myImageView = (ImageView) recycled;
}
String url = myUrls.get(position);
Glide
.with(myFragment)
.load(url)
.centerCrop()
.placeholder(R.drawable.loading_spinner)
.crossFade()
.into(myImageView);
return myImageView;
}
兼容性问题
*Android SDK:Glide需要最小API10。
*圆形图片: CircleImageView/CircularImageView/RoundedImageView 这些在TransitionDrawable和GIF动的时候有问题(.crossFade()的时候.thumbnail()或者.placeholder()),使用TransitionDrawable(.circleCrop()在v4中可用)或者.dontAnimate来修复这个问题。
* 超大图片(地图,漫画):Glide可以通过降采样的方式来加载超大的图片,但是不支持缩放,因为他们需要指定资源优化(比如平铺)来解决内存溢出。
懒惰配置
从Glide3.5开始,可以使用GlideModule接口来配置Glide并且可以在第一次请求Glide像ModelLoaders一样自动注册组件。
创建一个GlideMode
要想使用和注册一个GlideMode,首先需要实现配置和组件的接口:
package com.mypackage;
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.
}
}
可以实现多个GlideModlue,但是每一个必须得添加到ProGuard/DexGuard异常并且每一个必须在manifest中有单独的meta-data标签。添加到pro guard.cfg/proguard.pro文件会允许module通过反射来实例化。这样确保ProGuard和DexGuard不使它失效。这个反射性能的开销是最小的,因为当Glide第一次被请求创建的时候每个module只实例化一次。
-keepnames class com.mypackage.MyGlideModule
# or more generally:
#-keep public class * implements com.bumptech.glide.module.GlideModule
# for DexGuard only
-keepresourcexmlelements manifest/application/meta-data@value=GlideModule
<manifest ...>
<!-- ... permissions -->
<application ...>
<meta-data
android:name="com.mypackage.MyGlideModule"
android:value="GlideModule" />
<!-- ... activities and other components -->
</application>
</manifest>
库工程
库工程会定义一个或更多GlideModule。如果一个工程在它的manifest中添加了一个module,使用Gradle构建的应用(或者任何使用manifest合并的系统)依赖的库工程会自动pick up库的module。如果没有manifest合并可用,库module必须手动列到应用的manifest中。
全局配置
Glide允许配置一系列不同的全局的options来应用到全部请求。使用GlideModule#applyOptions提供的GlideBuilder。
硬盘缓存
使用GlideBuilder的setDiskCache()方法设置硬盘缓存的位置和最大值。也可以使用DiskCacheAdapter或者使用你自己实现的DiskCache接口来使默认的缓存不可用。硬盘缓存是在后台线程使用DiskCache.Factory接口构建来避免strict mode。
默认情况下Glide使用InternalCacheDiskCacheFactory类来构建硬盘缓存。这个内部缓存工厂将硬盘缓存放置在应用的内置缓存目录并且设置最大值为250M。使用这个缓存目录而不是SD卡意味着其他应用无法访问你下载的图片。
大小
builder.setDiskCache(
new InternalCacheDiskCacheFactory(context, yourSizeInBytes));
位置
builder.setDiskCache(
new InternalCacheDiskCacheFactory(context, cacheDirectoryName, yourSizeInBytes));
同样可以使用ExternalCacheDiskCacheFactory来将缓存放置到sd卡公共的缓存目录。
builder.setDiskCache(
new ExternalCacheDiskCacheFactory(context, cacheDirectoryName, yourSizeInBytes));
如果想使用其他自定义位置,可以使用DiskLruCacheFactory的不同构造方法:
// If you can figure out the folder without I/O:
// Calling Context and Environment class methods usually do I/O.
builder.setDiskCache(
new DiskLruCacheFactory(getMyCacheLocationWithoutIO(), yourSizeInBytes));
// In case you want to specify a cache folder ("glide"):
builder.setDiskCache(
new DiskLruCacheFactory(getMyCacheLocationWithoutIO(), "glide", yourSizeInBytes));
// In case you need to query the file system while determining the folder:
builder.setDiskCache(new DiskLruCacheFactory(new CacheDirectoryGetter() {
@Override public File getCacheDirectory() {
return getMyCacheLocationBlockingIO();
}
}), yourSizeInBytes);
注意:从Android 4.2开始,指定目录路径的硬编码不是一个好的方式,因为在一个设备上可以有多个用户。
如果想完全控制缓存的创建,可以自己实现DiskCache.Factory接口,然后使用DiskLruCacheWrapper在你想要的位置创建缓存。
builder.setDiskCache(new DiskCache.Factory() {
@Override public DiskCache build() {
File cacheLocation = getMyCacheLocationBlockingIO();
cacheLocation.mkdirs();
return DiskLruCacheWrapper.get(cacheLocation, yourSizeInBytes);
}
});
内存缓存和池
GlideBuilder类允许设置大小和实现Glide的MemoryCache和BitmapPool。
位置
默认大小是由MemorySizeCalculator这个类决定的。这个类会把屏幕尺寸可用的内存来给出一个合理的默认大小。如果想调整默认值需要构造自己的实例。
MemorySizeCalculator calculator = new MemorySizeCalculator(context);
int defaultMemoryCacheSize = calculator.getMemoryCacheSize();
int defaultBitmapPoolSize = calculator.getBitmapPoolSize();
如果想在你应用的一定时间段内动态调整Glide的内存足迹,这样使用:
Glide.get(context).setMemoryCategory(MemoryCategory.HIGH);
内存缓存
Glide的内存缓存是用来在内存中保持资源,这样他们不用通过执行I/O操作就可以立刻被使用。
使用GlideBuilder的setMemoryCache()方法来设置大小和实现你希望使用的内存缓存。LruResourceCache类是Glide的默认实现。可以以内存子节大小来自定义最大值:
builder.setMemoryCache(new LruResourceCache(yourSizeInBytes));
图片池
Glide的图片池用来允许图片的各种不同尺寸被重用,这样基本上可以减少被图片解码时引起像素数组分配的垃圾回收。
使用GlideBuilder的setBitmapPool()方法来设置和实现图片池。LruBitmapPool类是Glide的默认实现。LruBitmapPool类使用LRU算法来保持最近最常用的图片。通过下列代码可以以内存子节大小来自定义最大值:
builder.setBitmapPool(new LruBitmapPool(sizeInBytes));
图片格式
GlideBuilder类支持设置一个全局默认优先的图片配置。
默认情况下Glide会使用RGB_565,因为它只要求每个像素2个子节,这样会是系统默认最高质量ARGB_8888一半的内存消耗。但是RGB_565在处理某些条纹图片的时候会有问题而且不支持透明度。
如果在你应用中条纹是个问题而且你想要最可能高的图片质量,使用GlideBuild的setDecodeFormat方法设置DecodeFormat.ALWAYS_ARGB_8888作为Glide的优先图片配置。
builder.setDecodeFormat(DecodeFormat.ALWAYS_ARGB_8888);