Android图片载入框架最全解析(一),Glide的基本使用方法

时间:2022-01-14 08:32:06

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/53759439

本文同步发表于我的微信公众号。扫一扫文章底部的二维码或在微信搜索 郭霖 就可以关注,每天都有文章更新。

如今Android上的图片载入框架很成熟,从最早的老牌图片载入框架UniversalImageLoader,到后来Google推出的Volley,再到后来的新兴军Glide和Picasso,当然还有Facebook的Fresco。

每个都很稳定,功能也都十分强大。

可是它们的使用场景基本都是重合的。也就是说我们基本仅仅须要选择其中一个来进行学习和使用就足够了。每个框架都尝试去掌握的话则有些浪费时间。

在这几个框架其中,我对Volley和Glide研究得比較深入。对UniversalImageLoader、Picasso和Fresco都仅仅是有一些主要的了解。

从易用性上来讲,Glide和Picasso应该都是完胜其它框架的,这两个框架都实在是太简单好用了,大多数情况下载入图片都是一行代码就能解决的,而UniversalImageLoader和Fresco则在这方面略逊一些。

那么再拿Glide和Picasso对照呢,首先这两个框架的使用方法很类似,但事实上它们各有特色。Picasso比Glide更加简洁和轻量,Glide比Picasso功能更为丰富。之前已经有人对这两个框架进行过全方面的对照。大家假设想了解许多其它的话能够去參考一下 这篇文章

总之。没有最好的框架。仅仅有最适合自己的框架。

经过多方面对照之后,我还是决定选择了Glide来进行研究。而且这也是Google官方推荐的图片载入框架。

说实话。关于Glide的文章我已经筹备了好久。去年这个时候本来就打算要写了,可是一直都没有动笔。由于去年我的大部分时间都放在了写《第二行代码》上面,仅仅能用碎片时间来写写博客,可是Glide的难度远超出了我用碎片时间所能掌握的难度。

当然,这里我说的是对它的源代码进行解析的难度,不是使用上的难度。Glide的使用方法是很easy的。

所以,我认为去年我写不好Glide这个题材的文章。也就一直拖到了今年。

而如今。我花费了大量的精力去研究Glide的源代码和各种使用方法。相信如今已经能够将它很好地掌握了,因此我准备将我掌握的这些知识整理成一个新的系列,帮忙大家更好地学习Glide。

这个Glide系列大概会有8篇左右文章,估计花半年时间写完,将会包含Glide的基本使用方法、源代码解析、高级使用方法、功能扩展等内容,可能会是眼下互联网上最详尽的Glide教程。

那么本篇文章是这个系列的第一篇文章,我们先来了解一下Glide的基本使用方法吧。

開始

Glide是一款由Bump Technologies开发的图片载入框架,使得我们能够在Android平台上以极度简单的方式载入和展示图片。

眼下,Glide最新的稳定版本号是3.7.0,尽管4.0已经推出RC版了,可是临时问题还比較多。

因此,我们这个系列的博客都会使用Glide 3.7.0版本号来进行解说,这个版本号的Glide相当成熟和稳定。

要想使用Glide,首先须要将这个库引入到我们的项目其中。

新建一个GlideTest项目,然后在app/build.gradle文件其中加入例如以下依赖:

dependencies {
compile 'com.github.bumptech.glide:glide:3.7.0'
}

假设你还在使用Eclipse,能够点击 这里 下载Glide的jar包。

另外。Glide中须要用到网络功能,因此你还得在AndroidManifest.xml中声明一下网络权限才行:

<uses-permission android:name="android.permission.INTERNET" />

就是这么简单,然后我们就能够*地使用Glide中的随意功能了。

载入图片

如今我们就来尝试一下怎样使用Glide来载入图片吧。比方这是必应上一张首页美图的地址:

http://cn.bing.com/az/hprichbg/rb/Dongdaemun_ZH-CN10736487148_1920x1080.jpg

然后我们想要在程序其中去载入这张图片。

那么首先打开项目的布局文件。在布局其中加入一个Button和一个ImageView,例如以下所看到的:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Load Image"
android:onClick="loadImage"
/> <ImageView
android:id="@+id/image_view"
android:layout_width="match_parent"
android:layout_height="match_parent" /> </LinearLayout>

为了让用户点击Button的时候能够将刚才的图片显示在ImageView上,我们须要改动MainActivity中的代码。例如以下所看到的:

public class MainActivity extends AppCompatActivity {

    ImageView imageView;

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.image_view);
} public void loadImage(View view) {
String url = "http://cn.bing.com/az/hprichbg/rb/Dongdaemun_ZH-CN10736487148_1920x1080.jpg";
Glide.with(this).load(url).into(imageView);
} }

没错。就是这么简单。如今我们来执行一下程序,效果例如以下图所看到的:

Android图片载入框架最全解析(一),Glide的基本使用方法

能够看到。一张网络上的图片已经被成功下载。而且展示到ImageView上了。

而我们究竟做了什么?实际上核心的代码就仅仅有这一行而已:

Glide.with(this).load(url).into(imageView);

千万不要小看这一行代码,实际上仅仅就这一行代码。你已经能够做很许多的事情了,包含载入网络上的图片、载入手机本地的图片、载入应用资源中的图片等等。

以下我们就来具体解析一下这行代码。

首先,调用Glide.with()方法用于创建一个载入图片的实例。with()方法能够接收Context、Activity或者Fragment类型的參数。

也就是说我们选择的范围很广,无论是在Activity还是Fragment中调用with()方法。都能够直接传this。那假设调用的地方既不在Activity中也不在Fragment中呢?也没关系,我们能够获取当前应用程序的ApplicationContext,传入到with()方法其中。

注意with()方法中传入的实例会决定Glide载入图片的生命周期,假设传入的是Activity或者Fragment的实例,那么当这个Activity或Fragment被销毁的时候,图片载入也会停止。

假设传入的是ApplicationContext,那么仅仅有当应用程序被杀掉的时候。图片载入才会停止。

接下来看一下load()方法,这种方法用于指定待载入的图片资源。Glide支持载入各种各样的图片资源。包含网络图片、本地图片、应用资源、二进制流、Uri对象等等。因此load()方法也有许多个方法重载,除了我们刚才使用的载入一个字符串网址之外,你还能够这样使用load()方法:

// 载入本地图片
File file = new File(getExternalCacheDir() + "/image.jpg");
Glide.with(this).load(file).into(imageView); // 载入应用资源
int resource = R.drawable.image;
Glide.with(this).load(resource).into(imageView); // 载入二进制流
byte[] image = getImageBytes();
Glide.with(this).load(image).into(imageView); // 载入Uri对象
Uri imageUri = getImageUri();
Glide.with(this).load(imageUri).into(imageView);

最后看一下into()方法。这种方法就很easy了,我们希望让图片显示在哪个ImageView上。把这个ImageView的实例传进去就能够了。

当然。into()方法不仅仅是仅仅能接收ImageView类型的參数。还支持许多更丰富的使用方法。只是那个属于高级技巧,我们会在后面的文章其中学习。

那么回想一下Glide最主要的使用方式。事实上就是关键的三步走:先with(),再load(),最后into()。熟记这三步,你就已经入门Glide了。

占位图

如今我们来学一些Glide的扩展内容。事实上刚才所学的三步走就是Glide最核心的东西。而我们后面所要学习的所有东西都是在这个三步走的基础上不断进行扩展而已。

观察刚才载入网络图片的效果。你会发现,点击了Load Imagebutton之后,要略微等一会图片才会显示出来。

这事实上很easy理解,由于从网络上下载图片本来就是须要时间的。那么我们有没有办法再优化一下用户体验呢?当然能够。Glide提供了各种各样很丰富的API支持。其中就包含了占位图功能。

顾名思义,占位图就是指在图片的载入过程中,我们先显示一张临时的图片。等图片载入出来了再替换成要载入的图片。

以下我们就来学习一下Glide占位图功能的使用方法,首先我事先准备好了一张loading.jpg图片,用来作为占位图显示。然后改动Glide载入部分的代码。例如以下所看到的:

Glide.with(this)
.load(url)
.placeholder(R.drawable.loading)
.into(imageView);

没错,就是这么简单。

我们仅仅是在刚才的三步走之间插入了一个placeholder()方法。然后将占位图片的资源id传入到这种方法中就可以。

另外。这个占位图的使用方法事实上也演示了Glide其中绝大多数API的使用方法,事实上就是在load()和into()方法之间串接随意想加入的功能就能够了。

只是假设你如今又一次执行一下代码并点击Load Image,很可能是根本看不到占位图效果的。由于Glide有很强大的缓存机制,我们刚才载入那张必应美图的时候Glide自己主动就已经将它缓存下来了,下次载入的时候将会直接从缓存中读取。不会再去网络下载了,因而载入的速度很快,所以占位图可能根本来不及显示。

因此这里我们还须要略微做一点改动,来让占位图能有机会显示出来,改动代码例如以下所看到的:

Glide.with(this)
.load(url)
.placeholder(R.drawable.loading)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);

能够看到,这里串接了一个diskCacheStrategy()方法。并传入DiskCacheStrategy.NONE參数,这样就能够禁用掉Glide的缓存功能。

关于Glide缓存方面的内容我们将会在后面的文章进行具体的解说,这里仅仅是为了測试占位图功能而加的一个额外配置。临时你仅仅须要知道禁用缓存必须这么写就能够了。

如今又一次执行一下代码,效果例如以下图所看到的:

Android图片载入框架最全解析(一),Glide的基本使用方法

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ3VvbGluX2Jsb2c=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" title="">

能够看到,当点击Load Imagebutton之后会马上显示一张占位图。然后等真正的图片载入完毕之后会将占位图替换掉。

当然。这仅仅是占位图的一种,除了这种载入占位图之外,另一种异常占位图。异常占位图就是指,假设由于某些异常情况导致图片载入失败。比方说手机网络信号不好。这个时候就显示这张异常占位图。

异常占位图的使用方法相信你已经能够猜到了。首先准备一张error.jpg图片,然后改动Glide载入部分的代码,例如以下所看到的:

Glide.with(this)
.load(url)
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);

很easy,这里又串接了一个error()方法就能够指定异常占位图了。

如今你能够将图片的url地址改动成一个不存在的图片地址。或者干脆直接将手机的网络给关了,然后又一次执行程序。效果例如以下图所看到的:

Android图片载入框架最全解析(一),Glide的基本使用方法

这样我们就把Glide提供的占位图功能都掌握了。

指定图片格式

我们还须要再了解一下Glide另外一个强大的功能,那就是Glide是支持载入GIF图片的。这一点确实很牛逼,由于相比之下Jake Warton以前明白表示过,Picasso是不会支持载入GIF图片的。

而使用Glide载入GIF图并不须要编写什么额外的代码,Glide内部会自己主动推断图片格式。比方这是一张GIF图片的URL地址:

http://p1.pstatp.com/large/166200019850062839d3

我们仅仅须要将刚才那段载入图片代码中的URL地址替换成上面的地址就能够了,如今又一次执行一下代码,效果例如以下图所看到的:

Android图片载入框架最全解析(一),Glide的基本使用方法

也就是说,无论我们传入的是一张普通图片。还是一张GIF图片。Glide都会自己主动进行推断。而且能够正确地把它解析并展示出来。

可是假设我想指定图片的格式该怎么办呢?就比方说。我希望载入的这张图必须是一张静态图片。我不须要Glide自己主动帮我推断它究竟是静图还是GIF图。

想实现这个功能仍然很easy,我们仅仅须要再串接一个新的方法就能够了。例如以下所看到的:

Glide.with(this)
.load(url)
.asBitmap()
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);

能够看到,这里在load()方法的后面加入了一个asBitmap()方法,这种方法的意思就是说这里仅仅同意载入静态图片,不须要Glide去帮我们自己主动进行图片格式的推断了。

如今又一次执行一下程序,效果例如以下图所看到的:

Android图片载入框架最全解析(一),Glide的基本使用方法

由于调用了asBitmap()方法,如今GIF图就无法正常播放了。而是会在界面上显示第一帧的图片。

那么类似地。既然我们能强制指定载入静态图片,就也能强制指定载入动态图片。比方说我们想要实现必须载入动态图片的功能,就能够这样写:

Glide.with(this)
.load(url)
.asGif()
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);

这里调用了asGif()方法替代了asBitmap()方法。很好理解。相信不用我多做什么解释了。

那么既然指定了仅仅同意载入动态图片。假设我们传入了一张静态图片的URL地址又会怎么样呢?试一下就知道了,将图片的URL地址改成刚才的必应美图,然后又一次执行代码。效果例如以下图所看到的。

Android图片载入框架最全解析(一),Glide的基本使用方法

没错,假设指定了仅仅能载入动态图片,而传入的图片却是一张静图的话,那么结果自然就仅仅有载入失败喽。

指定图片大小

实际上。使用Glide在绝大多数情况下我们都是不须要指定图片大小的。

在学习本节内容之前,你可能还须要先了解一个概念。就是我们平时在载入图片的时候很easy会造成内存浪费。什么叫内存浪费呢?比方说一张图片的尺寸是1000*1000像素。可是我们界面上的ImageView可能仅仅有200*200像素,这个时候假设你不正确图片进行不论什么压缩就直接读取到内存中,这就属于内存浪费了,由于程序中根本就用不到这么高像素的图片。

关于图片压缩这方面,我之前也翻译过Android官方的一篇文章,感兴趣的朋友能够去阅读一下 Android高效载入大图、多图解决方式。有效避免程序OOM

而使用Glide,我们就全然不用操心图片内存浪费,甚至是内存溢出的问题。

由于Glide从来都不会直接将图片的完整尺寸所有载入到内存中,而是用多少载入多少。Glide会自己主动推断ImageView的大小,然后仅仅将这么大的图片像素载入到内存其中。帮助我们节省内存开支。

当然。Glide也并没有使用什么奇妙的魔法。它内部的实现原理事实上就是上面那篇文章其中介绍的技术,因此掌握了最主要的实现原理,你也能够自己实现一套这种图片压缩机制。

也正是由于Glide是如此的智能,所以刚才在開始的时候我就说了,在绝大多数情况下我们都是不须要指定图片大小的,由于Glide会自己主动依据ImageView的大小来决定图片的大小。

只是,假设你真的有这种需求,必须给图片指定一个固定的大小。Glide仍然是支持这个功能的。改动Glide载入部分的代码,例如以下所看到的:

Glide.with(this)
.load(url)
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.override(100, 100)
.into(imageView);

仍然很easy,这里使用override()方法指定了一个图片的尺寸,也就是说,Glide如今仅仅会将图片载入成100*100像素的尺寸,而不会管你的ImageView的大小是多少了。

好了。今天是我们这个Glide系列的第一篇文章。写了这么多内容已经算是挺不错的了。如今你已经了解了Glide的基本使用方法,当然也是一些最经常使用的使用方法。下一篇文章其中,我们会尝试去分析Glide的源代码,研究一下在这些基本使用方法的背后。Glide究竟执行了什么奇妙的操作。能够使得我们载入图片变得这么简单?感兴趣的朋友请继续阅读 Android图片载入框架最全解析(二),从源代码的角度理解Glide的执行流程

关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

微信扫一扫下方二维码就可以关注:

Android图片载入框架最全解析(一),Glide的基本使用方法         Android图片载入框架最全解析(一),Glide的基本使用方法