【Android - 框架】之Glide的使用
一、Glide简介:
Glide是Google官方推荐的一个图片加载和缓存的开源库,它不仅能实现平滑的图片列表滚动效果,还支持远程图片的获取、大小调整和展示,并且可以加载GIF图片。Glide相比与UIF、Volley、Picasso、Fresco等其他框架的优点是轻量和稳定。
二、Glide的配置:
使用Glide首先需要导入Glide的依赖,在build.gradle文件中添加:
compile 'com.github.bumptech.glide:glide:3.7.0'
如果Glide需要从网络中加载图片,则还需要在Manifest文件中添加网络访问权限:
<uses-permission android:name="android.permission.INTERNET" />
Glide为我们提供了一个GlideModule接口,其中提供了一系列Glide配置的抽象方法,我们可以创建一个类实现这个接口,并在实现的方法中设置Glide的一些配置项,如自定义缓存大小和位置、自定义内存和图片池大小、自定义图片格式等。一个GlideModule的实现类样板如下:
public class GlideConfig implements GlideModule {
int diskSize = 1024 * 1024 * 100;
int memorySize = (int) (Runtime.getRuntime().maxMemory()) / 8; // 取1/8最大内存作为最大缓存 @Override
public void applyOptions(Context context, GlideBuilder builder) {
// 定义缓存大小和位置
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, diskSize)); // 内存中
// builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, "cache", diskSize)); // sd卡中 // 默认内存和图片池大小
// MemorySizeCalculator calculator = new MemorySizeCalculator(context);
// int defaultMemoryCacheSize = calculator.getMemoryCacheSize(); // 默认内存大小
// int defaultBitmapPoolSize = calculator.getBitmapPoolSize(); // 默认图片池大小
// builder.setMemoryCache(new LruResourceCache(defaultMemoryCacheSize));
// builder.setBitmapPool(new LruBitmapPool(defaultBitmapPoolSize)); // 自定义内存和图片池大小
builder.setMemoryCache(new LruResourceCache(memorySize)); // 自定义内存大小
builder.setBitmapPool(new LruBitmapPool(memorySize)); // 自定义图片池大小 // 定义图片格式
// builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
builder.setDecodeFormat(DecodeFormat.PREFER_RGB_565); // 默认
} @Override
public void registerComponents(Context context, Glide glide) {
}
}
GlideConfig类完成之后,我们需要在Manifest文件中注册这个类,便于Glide找到这个类并进行初始化配置。在Manifest的<application>标签下添加一个<meta-data>标签,在其中注册这个类:
<!-- 注册Glide的配置文件,以便Glide能够找到 -->
<meta-data
android:name="com.example.itgungnir.testglide.GlideConfig"
android:value="GlideModule" />
到此为止,Glide的基础配置就完成了。
三、Glide的使用:
Glide中的常用方法如下:
.with() 图片加载的环境:1,Context对象。2,Activity对象。3,FragmentActivity对象。4,Fragment对象
.load() 加载资源:1,drawable资源。2,本地File文件。3,uri。4,网络图片url。5,byte数组(可以直接加载GIF图片)
.placeholder() 图片占位符
.error() 图片加载失败时显示
.crossFade() 显示图片时执行淡入淡出的动画默认300ms
.dontAnimate() 不执行显示图片时的动画
.override() 设置图片的大小
.centerCrop() 和 fitCenter() 图片的显示方式
.animate() view动画 2个重构方法
.transform() bitmap转换
.bitmapTransform() bitmap转换。比如旋转,放大缩小,高斯模糊等(当用了转换后你就不能使用.centerCrop()或.fitCenter()了。)
.priority(Priority.HIGH) 当前线程的优先级
.signature(new StringSignature(“ssss”))
.thumbnail(0.1f) 缩略图,3个重构方法:优先显示原始图片的百分比(10%)
.listener() 异常监听
.into() 图片加载完成后进行的处理:1,ImageView对象。2,宽高值。3,Target对象
我们用以下两个地址来完成Glide框架的测试,两个地址都是网络图片的URL地址,一个是静态图片的地址,另一个是GIF图片的地址:
private static final String IMAGE_STATIC_URL = "http://download.pchome.net/wallpaper/pic-2532-1.jpg"; // 静态图片
private static final String IMAGE_GIF_URL = "http://img1.gamedog.cn/2013/06/22/43-1306220944560.gif"; // GIF图片
1、Glide的基本用法:
Glide.with(MainActivity.this) // 在MainActivity中调用Glide的API
.load(IMAGE_STATIC_URL) // 加载网络中的静态图片
.placeholder(R.mipmap.ic_launcher) // 在图片没有加载出来或加载失败时显示ic_launcher图片
.into(iv); // 将图片加载到一个ImageView对象中
.with()方法中的参数可以有四种类型;.load()方法中的参数可以有五种类型,这里就不多说了,在上面都有,这里重点说一下.into()方法。.into()方法中的参数有三种类型:
可以是一个ImageView对象,表示图片加载完成之后直接放到ImageView中进行展示,如上面的代码。
可以是一个宽度值和一个高度值,指定期望得到的图片的宽高值,返回一个GlideDrawable对象。这个方法必须在子线程中进行,具体原因有待研究。贴上代码:
final Handler glideHanlder = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
GlideDrawable glideDrawable = (GlideDrawable) msg.obj;
iv.setImageDrawable(glideDrawable);
}
}
};
new Thread(new Runnable() {
@Override
public void run() {
try {
GlideDrawable glideDrawable = Glide.with(MainActivity.this) // 在MainActivity中调用Glide的API
.load(IMAGE_STATIC_URL) // 加载网络中的静态图片
.placeholder(R.mipmap.ic_launcher) // 在图片没有加载出来或加载失败时显示ic_launcher图片
.into(200, 400) // 设置期望得到的图片的宽高值
.get(); // 获取到GlideDrawable对象
Message msg = Message.obtain();
msg.what = 1;
msg.obj = glideDrawable;
glideHanlder.sendMessage(msg);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}).start();
也可以是一个Target接口、Target接口的子类或实现类,可以有如下图所示的选项:
使用不同的类或接口作为参数,根据回调的方法进行操作即可。这里贴出使用SimpleTarget的代码:
Glide.with(MainActivity.this) // 在MainActivity中调用Glide的API
.load(IMAGE_STATIC_URL) // 加载网络中的静态图片
.into(new SimpleTarget<GlideDrawable>() { // 图片加载回调的Target实现类
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
// 图片加载成功时回调的方法
iv.setImageDrawable(resource);
}
});
2、其他方法解释:
.asBitmap()和.asGif()
如果调用了.asBitmap()方法,则.load()中的参数指向的可以是一个静态图片也可以是GIF图片,如果是一张GIF图片,则加载之后只会展示GIF图片的第一帧
如果调用的.asGif()方法,则.load()方法中的参数指向的必须是一个GIF图片,如果是一张静态图片,则图片加载完成之后展示的只是图片占位符(如果没有设置图片占位符,则什么也不展示)
这两个方法中只能调用一个,调用了其中一个方法之后,代码提示就不会提示另一个了。代码:
Glide.with(MainActivity.this) // 在MainActivity中调用Glide的API
.load(IMAGE_STATIC_URL) // 加载网络中的静态图片
.asBitmap() // 将图片固定成静态图片
.placeholder(R.mipmap.ic_launcher) // 图片占位符
.into(iv); // 图片加载完成后直接放到ImageView对象iv中进行展示
.override()
这个方法可以设置图片加载之后展示的宽度值和高度值,前提是目标ImageView的宽度和高度都设置为wrap_content。代码:
Glide.with(MainActivity.this) // 在MainActivity中调用Glide的API
.load(IMAGE_STATIC_URL) // 加载网络中的静态图片
.override(666, 666) // 设置加载之后的图片显示的宽度和高度
.placeholder(R.mipmap.ic_launcher) // 图片占位符
.into(iv); // 图片加载完成后直接放到ImageView对象iv中进行展示
.thumbnail()
设置这个方法之后,可以先加载这张图片的sizeMultiplier倍的缩略图到目标ImageView中,然后再慢慢加载完整的图片。sizeMultiplier值的范围是0~1。代码:
Glide.with(MainActivity.this) // 在MainActivity中调用Glide的API
.load(IMAGE_STATIC_URL) // 加载网络中的静态图片
.thumbnail(0.1f) // 先加载一定比例的缩略图
.placeholder(R.mipmap.ic_launcher) // 图片占位符
.into(iv); // 图片加载完成后直接放到ImageView对象iv中进行展示
.animate()
加载图片时展示的动画,可以是Animator类型的属性动画,也可以是int类型的动画资源。这个动画只在第一次加载的时候会展示,以后都会从缓存中获取图片,因此也就不会展示动画了。代码:
Glide.with(MainActivity.this) // 在MainActivity中调用Glide的API
.load(IMAGE_STATIC_URL) // 加载网络中的静态图片
.animate(android.R.anim.slide_in_left) // 图片加载完成后的动画效果(从左侧滑入)
.into(iv); // 图片加载完成后直接放到ImageView对象iv中进行展示
.centerCrop()和.fitCenter()
如果调用了.centerCrop()方法,则显示图片的时候短的一边填充容器,长的一边跟随缩放
如果调用了.fitCenter()方法,则显示图片的时候长的一边填充容器,短的一边跟随缩放
这两个方法可以都调用,如果都调用,则最终显示的效果是后调用的方法展示的效果。代码:
Glide.with(MainActivity.this) // 在MainActivity中调用Glide的API
.load(IMAGE_STATIC_URL) // 加载网络中的静态图片
.fitCenter() // 长的一边填充容器
.centerCrop() // 短的一边填充容器
.into(iv); // 图片加载完成后直接放到ImageView对象iv中进行展示
.bitmapTransform()
.bitmapTransform()方法中传入的参数是一组Transformation类型的对象,即转换器,可以是任意多个。要想使用Glide为我们提供的转换器,我们需要先在build.gradle文件中导入Glide的Transformations的依赖:
compile 'jp.wasabeef:glide-transformations:1.0.6'
这个依赖中为我们提供了很多的转换器,如下:
圆形:CropCircleTransformation
方形:CropSquareTransformation
圆角:RoundedCornersTransformation
颜色覆盖:ColorFilterTransformation
置灰:GrayscaleTransformation
毛玻璃:BlurTransformation
使用转换器的时候直接new就可以了,但是需要传入一个BitmapPool的对象,我们可以直接传入一个new的LruBitmapPool。例如,我们想得到一个圆形图片的转换器,就可以编写如下代码:
LruBitmapPool pool = new LruBitmapPool((int) (Runtime.getRuntime().maxMemory()) / 8);
Glide.with(MainActivity.this) // 在MainActivity中调用Glide的API
.load(IMAGE_STATIC_URL) // 加载网络中的静态图片
.fitCenter() // 长的一边填充容器
.centerCrop() // 短的一边填充容器
.bitmapTransform(new CropCircleTransformation(pool)) // 转换器
.into(iv); // 图片加载完成后直接放到ImageView对象iv中进行展示
.resumeRequests()和.pauseRequests()
这两个方法是为了保证用户界面的滑动流畅而设计的。当在ListView中加载图片的时候,如果用户滑动ListView的时候继续加载图片,就很有可能造成滑动不流畅、卡顿的现象,这是由于Activity需要同时处理滑动事件以及Glide加载图片。Glide为我们提供了这两个方法,让我们可以在ListView等滑动控件滑动的过程中控制Glide停止加载或继续加载,可以有效的保证界面操作的流畅。
我们需要在ListView的OnScrollListener中写这部分的代码,如下(Adapter中的代码就不贴出来了):
// ListView滑动时触发的事件
lv.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
case AbsListView.OnScrollListener.SCROLL_STATE_FLING:
// 当ListView处于滑动状态时,停止加载图片,保证操作界面流畅
Glide.with(MainActivity.this).pauseRequests();
break;
case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
// 当ListView处于静止状态时,继续加载图片
Glide.with(MainActivity.this).resumeRequests();
break;
}
} @Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
四、Glide的原理:
当Glide调用with()方法时,通过传入的Context对象获取一个RequestManager对象。RequestManager类中封装了一个RequestTracker,RequestTracker中有一个List<Request>集合,用来统一管理Request请求。
当RequestManager对象调用load()方法时,将参数中的值(String或URL或byte[])封装成一种ModelType类型的数据存储到GenericRequestBuilder对象中,并返回一个DrawableRequestBuilder类型的对象(DrawableRequestBuilder是GenericRequestBuilder的子类)。
当DrawableRequestBuilder对象调用into()方法时,会调用其父类GenericRequestBuilder的obtainRequest()方法,返回一个GenericRequest对象(这个对象是Request接口的一个实现类)。
GenericRequest对象经过一系列的准备工作之后,调用Engine对象的load()方法开始加载图片。load()方法的加载流程如下:
* Check the memory cache and provide the cached resource if present
* Check the current set of actively used resources and return the active resource if present
* Check the current set of in progress loads and add the cb to the in progress load if present
* Start a new load
正如上面的源码注释中介绍的一样,Glide首先去缓存中寻找图片(这个缓存就是一个图片池BitmapPool),如果缓存中有这张图片,则从缓存资源中取出图片进行加载;如果缓存中没有,则从“actively used resources”中找图片,源码中的“actively used resources”指的是一个弱引用组成的Map集合,即如果缓存中没有,就去弱引用中找这张图片,如果弱引用中有这张图片则从弱引用中取出来进行加载;如果弱引用中也没有,则从正在进行的load(Request)中查找有没有哪个Request正在加载这张图片,如果有的话就等待这个Request加载完成之后直接拿过来加载;如果还是没有的话,就只能新开启一个Request从网络中获取了。
从上面的分析可以看到,Glide加载图片的方式和三级缓存机制很像,Glide中的缓存BitmapPool就像三级缓存中的强引用LruCache,Glide中也有一个弱引用的集合。唯一不同的是,Glide中对正在进行的请求也做了筛选,保证同一张图片只建立一个Request进行加载即可。
这里顺便科普一下强引用和弱引用之间的工作流程:强引用是一片固定的空间,使用队列的形式存储数据,新来的图片存到队尾,这样可以保证队尾的永远都是最新、最后使用的图片,对头都是最老、最早使用的图片。当强引用中的空间存满的时候,会把对头的图片“踢”出来放到弱引用中。我们之所以要使用弱引用,是因为弱引用可以在内存满了的时候随时GC,因此通常都会用弱引用作为第二级缓存。
以上就是对Glide的工作流程的总结,有不对之处还望大家不吝赐教,谢谢!
【Android - 框架】之Glide的使用的更多相关文章
- 【Android 进阶】图片载入框架之Glide
简单介绍 在泰国举行的谷歌开发人员论坛上,谷歌为我们介绍了一个名叫 Glide 的图片载入库,作者是 bumptech.这个库被广泛的运用在 google 的开源项目中,包含 2014 年 googl ...
- 一个C#开发搭建Android框架的心路历程
前言 Java框架实在是太多了,因为是初学乍练,所以,只好以百度为标准选择框架了. Java的框架文章太难写了,因为他引用了太多框架,而没一个框架都有很繁琐的配置,把每个框架都写一遍,就等于写书了:所 ...
- Android 框架简介--Java环境(转)
==========================上=========================== 这里简单的介绍了Android的java环境基础,在后面一节中会结合具体的实例来理解这一节 ...
- 【Android - 框架】之GreenDao的使用
上一篇博客([Android - 框架]之ORMLite的使用)中介绍了ORMLite的基本使用,今天我们来研究以下GreenDao的使用. GreenDao和ORMLite一样,都是基于ORM(Ob ...
- 【Android - 框架】之Retrofit+RxJava的使用
前几天分别对Retrofit和RxJava进行了总结,这个帖子打算把Retrofit结合RxJava使用的方法总结以下.有还不了解Retrofit或RxJava的朋友可以参考下面的帖子学习~ [And ...
- IOS 与ANDROID框架及应用开发模式对照一
IOS 和ANDROID操作系统都是眼下流行的移动操作系统,被移动终端和智能设备大量採用,两者都採用了先进的软件技术进行设计,为了方便应用开发两者都採用了先进的设计模式. 两者在框架设计上都採用了什么 ...
- Kotlin的扩展函数:扩展Android框架(KAD 08)
作者:Antonio Leiva 时间:Jan 11, 2017 原文链接:https://antonioleiva.com/extension-functions-kotlin/ 扩展函数是Kotl ...
- App 组件化/模块化之路——Android 框架组件(Android Architecture Components)使用指南
面对越来越复杂的 App 需求,Google 官方发布了Android 框架组件库(Android Architecture Components ).为开发者更好的开发 App 提供了非常好的样本. ...
- 【Android 系统开发】Android框架 与 源码结构
一. Android 框架 Android框架层级 : Android 自下 而 上 分为 4层; -- Linux内核层; -- 各种库 和 Android运行环境层; -- 应用框架层; -- 应 ...
- IOS 与ANDROID框架及应用开发模式对比一
IOS 和ANDROID操作系统都是目前流行的移动操作系统,被移动终端和智能设备大量采用,两者都采用了先进的软件技术进行设计,为了方便应用开发两者都采用了先进的设计模式.两者在框架设计上都采用了什么技 ...
随机推荐
- 【实习记】2014-08-18使用curl排错http头的content-length
总结一,用curl排错Content-Length设置错误,误导了客户端. 访问/cgi-bin/txproj_list时,firebug显示总是不多不少15秒,调试其他问题时郁闷. fire ...
- compser 执行命令提示do not run composer as root/super !
这个是因为composer为了防止非法脚本在root下执行,解决办法随便切换到非root用户即可
- QML之TextEdit
TextEdit显示一个可编辑的,有格式的文本框.它也可以显示明文和富文本.例如:TextEdit { width: 240 text: "<b>Hello</ ...
- C#获取硬盘空间信息
/// <summary> /// 获取指定驱动器的空间总大小(单位为B) /// </summary> /// <param name="str_HardDi ...
- VMware内安装Ubuntu后安装vmtools
今天处于好奇安装了Ubuntu,可是虚拟机运行的时候发现界面很小,于是百度发现要安装一个工具,看了很多方法,就这个比较实用,和大家分享: 第一步:进入系统后,点击虚拟机上的安装vmware tools ...
- matlab提速技巧(自matlab帮助文件)
matlab提速技巧(自matlab帮助文件) 1.首先要学会用profiler.1.1. 打开profiler.To open the Profiler, select View -> Pro ...
- 【MongoDB】应用场景
24 Use Cases24.1 适合场景 Archiving and event logging 归档和日志记录 Document and Content Management Systems ...
- 【Java】Java里String 的equals和==
Java里面有对象和对象的引用的概念,在String方面,==比较的是引用,equals比较的是对象的具体值. String s1 = new String("abc");Stri ...
- 【转】Open XML SDK class structure
Open XML SDK class structure March 27, 2012 by Vincent I’ve gotten a few questions on the class stru ...
- Android中SharedPreferences和序列化结合保存对象数据
前言: 最近在做用户注册的时候,遇到了需要填写很多表单数据,不可能在一页把所有的数据都展示完全,因此采用了分页的方式,由于在用户填写数据数据之后我们需要对用户填写的数据进行暂时的记录的,当用户会到此页 ...