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

推荐阅读更多精彩内容