在泰国举行的谷歌开发者论坛上,谷歌为我们介绍了一个名叫 Glide 的图片加载框架,作者是 bumptech,这个库被广泛的应用在 Google 开源项目中,包括 年 Google I/O 大会上发布的官方 App,现在 Android 开发中已经有非常多的图片类的加载框架库,有前几年非常流行的 ImageLoader,以及现在的 Picasso、Fresco 等一些非常稳定和流行的框架,并且每一个功能都非常强大,但我们终究还是要选择一个进行学习,这里我选择 Glide,因为从简单易用性方面来说,Picasso 和 Glide 更简单易用,功能上都非常强大,但是 Picasso 和 Glide 相比较,Picasso 更加简洁,也更轻量,但 Glide 功能也更为丰富,但是事情总是没有绝对的,没有最好的最好的框架,可以根据项目的需求选择自己更合适的,接下来我们开始解析
一、概述
下面我们简单的描述一下 Glide 图片开发框架的相关情况:
1)简单易用
2)可配置度高,自适应程度强
3)支持常见的图片格式,Jpg、png、gif、webp 等
4)支持各种数据源,网络、本地、资源、Assets 等
5)高效缓存策略,支持 Memory 和 Disk 图片缓存,默认 Bitmap 格式采用 RGB_565 内存使用至少减少一半
6)生命周期集成根据 Activity/Fragment 生命周期自动管理请求
7)高效处理 Bitmap,主动调用 recycle 回收需要回收的 Bitmap 减小系统回收压力
8)下载地址:/bumptech/glide
二、使用
要使用 Glide,首先要把这个库引入到我们的项目中,新建一个 GlideSample 项目,然后在 app 模块的 build.gradle 里添加如下依赖:
这里需要注意的是如果项目依赖库里没有 support-v4 的支持库的话也需要添加一下
dependencies {compile 'com.github.bumptech.glide:glide:3.7.0'compile 'com.android.support:support-v4:19.1.0'}
另外 Glide 需要用到网络,需要在 AndroidManifest.xml 中声明一下网络权限:
<uses-permission android:name="android.permission.INTERNET"/>
到这里我们就可是使用 Glide 的所有功能了
接下来我们就来使用 Glide 来加载一张图片:
图片路径:/file/0601/13044986_145039092624_2.jpg
那么接下来在布局文件中加入一个 ImageView 和一个 Button 如下所示:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:id="@+id/activity_glide"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.example.qiudengjiao.glidesample.GlideActivity"><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="load"android:text="点击加载图片" /><ImageViewandroid:id="@+id/iv_image"android:layout_width="match_parent"android:layout_height="wrap_content" /></LinearLayout>
接下来我们来写 GlideActivity 中的代码如下:
/*** Glide图片加载框架测试*/public class GlideActivity extends AppCompatActivity {ImageView image;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_glide);initView();}private void initView() {image = (ImageView) findViewById(R.id.iv_image);}/*** 响应图片加载的点击事件** @param view*/public void load(View view) {String url = "/file/0601/13044986_145039092624_2.jpg";//这里就是加载图片的代码Glide.with(GlideActivity.this).load(url).into(image);}}
这样我们的图片就成功加载了,就是这么简单,一行代码搞定,我们运行一下程序来欣赏一下美丽的金门大桥:
可以看到网络上的金门大桥图片已经被成功加载,并且展示到了我们的 ImageView 上
而我们只写了一行简单的代码:
Glide.with(GlideActivity.this).load(url).into(image);
接下来我们对这行代码进行解析:
1)先看 Glide.with() 方法:
在这里我们首先调用了 Glide.with() 方法,创建一个实例,然后我们来看 with 里面接受的参数,这里接受 Context、Activity、FragmentActivity、Fragment 类型的参数,这里也就是说不管是在 Activity 还是在 Fragment 中调用 with() 方法,直接传入 this 就好,但是如果不在 Activity 或者 Fragment 中我们还可以直接传应用程序的上下文 ApplicationContext,这里需要注意的是,就像我们上面概述第六条里说的:Glide 生命周期集成根据 Activity/Fragment 生命周期自动管理请求,也就是说,with 方法里面传入的实例Fragment、Activity、FragmentActivity、ApplicationContext,会影响 Glide 的生命周期,如果是 Fragment 或 Activity、FragmentActivity 那么当相对应的 Fragment 和 Activity 和 FragmentActivity 销毁的时候,图片加载也会停止,如果传入的是应用的上下文 ApplicationContext 那么只有当应用销毁的时候,图片加载才会停止,为了大家看起来简单明了
总结如下:
with(Context context) 使用 Application 上下文,Glide 请求将不受 Activity/Fragment 生命周期控制with(Activity activity) 使用 Activity 上下文,Glide 请求将受到 Activity 生命周期控制with(Fragment fragment) 使用 Fragment 上下文,Glide 请求将受到 Fragment 生命周期控制with(FragmentActivity activity) Glide 请求将会受到 FragmentActivity 生命周期的控制 返回关联了相应上下文的 RequestManager 实例,我们简单看一下源码如下:
public static RequestManager with(Context context) {RequestManagerRetriever retriever = RequestManagerRetriever.get();return retriever.get(context);}
public static RequestManager with(Activity activity) {RequestManagerRetriever retriever = RequestManagerRetriever.get();return retriever.get(activity);}
public static RequestManager with(FragmentActivity activity) {RequestManagerRetriever retriever = RequestManagerRetriever.get();return retriever.get(activity);}
public static RequestManager with(android.app.Fragment fragment) {RequestManagerRetriever retriever = RequestManagerRetriever.get();return retriever.get(fragment);}
public static RequestManager with(Fragment fragment) {RequestManagerRetriever retriever = RequestManagerRetriever.get();return retriever.get(fragment);}
如果想看得更明白,大家可以在自己的代码里具体看
2)再看 load() 方法:
同样我们来看 load() 方法中能传入的实例,可以是 String、Uri、File、Integer、byte[] 等,也就是说支持加载各种图片资源,包括网络图片、Uri 对象、本地图片、应用资源、二进制流等等,
//这里就是加载图片的代码(网络图片)Glide.with(GlideActivity.this).load(url).into(image);//加载UriUri image = getImageUri();Glide.with(GlideActivity.this).load(image).into(image1);//加载本地图片File file = new File(getExternalCacheDir()+"/image.jpg");Glide.with(GlideActivity.this).load(file).into(image2);//加载应用资源int resource = R.drawable.ic_launcher;Glide.with(GlideActivity.this).load(resource).into(image3);//加载二进制流byte[] image = getImageBytes();Glide.with(GlideActivity.this).load(image).into(image4);
3)接下来看最后一个 into() 方法:
这里就是你要往哪个 ImageView 控件上显示,把对应实例传进去就好了,这里我们来总结一下 Glide 的用法,先 with(),再 load(),最后 into(),这样 Glide 的最简单用法我们就介绍完了,相信你对这三步也更加理解了一些,深入的理解的话我们可以去点进去看相关的源码,我们上面说到的都能看到
4)指定图片的大小:
/*** 响应图片加载的点击事件** @param view*/public void load(View view) {String url = "/file/0601/13044986_145039092624_2.jpg";//这里就是加载图片的代码Glide.with(GlideActivity.this).load(url).override(200, 300).into(image);}
这里我们在刚才代码的 load() 方法和 into() 方法中间加了一个 override() 方法,直接传入int类型的值就可以指定和调整图片的尺寸,一般实际在项目里面,我们都不在这里指定图片的大小,可以在 xml 文件里面直接指定,Glide 可以防止内存的浪费和溢出,因为 Glide 从来不会将图片的完整尺寸加载到内存中,用多少加载多少,Glide 会自动判断 ImageView 的大小,可以有效色避免运行程序的 OOM
5)占位图
我们在实际项目的应用中,图片的加载往往有一个过程,如果是从网络上下载图片,就会有等待的过程,因为图片的加载都需要一定的时间,这样在网络不好的情况下,用户往往只能看到一片空白,感觉不是很好,为了有更好的额体验,我们可以先显示一张占位图,等图片加载出来再替代占位图,修改代码加载如下:
Glide.with(GlideActivity.this).load(url).override(200, 300).placeholder(R.drawable.ic_launcher).into(image);
这里我们又插入了一个 placeholder() 方法,然后将图片的资源 Id 传入即可,为了方便起见这里我们直接用默认系统自带的小机器人图片,在实际项目中大家可以换成 UI 规定的图片,到这里我们大概也就明白了,我们想要添加什么功能,只需要在 load() 方法和 into() 方法中间去添加相应的方法就好了,我们概述里第一条说的简单易用就完全体现出来了,我们运行程序,根本都没有看到占位图,这是什么鬼,难道是我们的代码有问题?我们的代码没有任何问题,这是因为 Glide 自带缓存机制,我们刚才加载的图片 Glide 已经缓存下来了,再次加载就会从缓存中直接读取,不会再去网络中加载,这样显示的速度就特别快,所以我们看能看不到先有占位图的效果,为了让占位图显示出来,我们修改代码如此下:
Glide.with(GlideActivity.this).load(url).override(200, 300).placeholder(R.drawable.ic_launcher).diskCacheStrategy(DiskCacheStrategy.NONE).into(image);
可以看到我们又在中间插入了一个 diskCacheStrategy() 方法,并且传入了 diskCacheStrategy.NONE 参数,利用这句代码我们就禁止了 Glide 的缓存功能,当然这里我们只是为了能够更好的去看到占位图,实际项目中大多情况下我们用不到,因为这样我们将会非常的消耗用户的流量,另外 Glide 还为我们提供了异常占位图,用发和上面的类似,使用 error() 方法,这样可以防止在某些异常情况下图片加载失败的情况下用来显示,这里我们也用系统图片代替了,用法如下:
Glide.with(GlideActivity.this).load(url).override(200, 300).placeholder(R.drawable.ic_launcher).error(R.drawable.ic_launcher).diskCacheStrategy(DiskCacheStrategy.NONE).into(image);
6)支持加载 GIF 图片
这里就要介绍 Gilde 的大招,也是 Glide 一个非常强大的功能,是 Picasso 所不具备的,那就是 Glide 支持加载 GIF 图片,这里给大家提供一个动图的地址如下:
这里本来想给大家展示一下的,但遗憾没有转化成功,大家就自行在程序里看一下吧
地址:/DownloadImg//02/0520/65575746_6.gif
这里大家直接传入 load() 里就好,Glide 会自动判断是静态图还是 GIF 图,并且可以正确的解析出来
7)下面对一些方法进行简单介绍:
asGif() 把资源作为 GifDrawable 对待,如果资源不是 gif 动画,将会加载失败,回调我们上面提到的 error() 方法 asBitmap() 无论资源是不是 gif 动画都作为 Bitmap 对待,如果是 gif 动画会停在第一帧 diskCacheStrategy(DiskCacheStrategy strategy) 设置缓存策略。DiskCacheStrategy.SOURCE:缓存原始数据,DiskCacheStrategy.RESULT:缓存变换(如缩放、裁剪等)后的资源数据,DiskCacheStrategy.NONE:什么都不缓存,DiskCacheStrategy.ALL:缓存SOURC和RESULT。默认采用DiskCacheStrategy.RESULT 策略,对于 download only 操作要使用 DiskCacheStrategy.SOURCE thumbnail(float sizeMultiplier) 请求给定系数的缩略图,如果缩略图比全尺寸图先加载完,就显示缩略图,否则就不显示。系数sizeMultiplier必须在(0,1)之间,可以递归调用该方法 priority(Priority priority) 指定加载的优先级,优先级越高越优先加载,但不保证所有图片都按序加载。枚举 Priority.IMMEDIATE、Priority.HIGH、Priority.NORMAL、Priority.LOW,默认为 Priority.NORMAL sizeMultiplier(float sizeMultiplier). 在加载资源之前给 Target 大小设置系数 今天的内容就写到这里,只是对 Glide 的相关用法做了简单的介绍,大家可以更加深入的去了解 Glide 的背后实现原理
如果觉得《Android Glide 图片加载框架解析》对你有帮助,请点赞、收藏,并留下你的观点哦!