Android
开发过程中,图片加载基本是每个项目都必备的功能,图片加载的开源项目也比较多,从最老牌的Android-Universal-Image-Loader,到后来Google
的Volley再到良心公司Square
的Picasso以及FaceBook
的Fresco和Google IO
开发者大会上推荐的Glide。
面对这么多的加载库我们该如何去选择? 他们各有优缺点,没法绝对的来说哪个是最好的,只有根据自己的需要来选择最适合自己的,接下来我们就重点分析下这几个项目的优缺点。
最老牌的图片加载库,提供了丰富的配置,简单易用,但是从2015.11
开始就已经停止维护了,在当前信息技术高速发展的时代,停止维护我们就只能放弃了。
但是不得不说,他是一个很优秀的项目。
优点:
- 支持
Gif
图片。 - 支持
WebP
。 - 加载速度快、流畅度高。
Glide
的with()
方法不光接受Context
,还接受Activity
和Fragment
,这样图片加载会和Activity/Fragment
的生命周期保持一致,比如Pause
状态在暂停加载,在Resume
的时候又自动重新加载。- 支持设置图片加载优先级。
- 支持缩略图,可以在同一时间加载多张图片到同一个
ImageView
中,例如可以首先加载只有ImageView
十分之一大小的缩略图,然后等再加载完整大小的图片后会再显示到该ImageView
上。 - 内存占用低,
Glide
默认的Bitmap
格式是RGB_565
,比ARGB_8888
格式的内存开销要小一半,所以图片质量会稍微差一些,当然这些配置都是可以修改的。 Glide
缓存的图片大小是根据ImageView
尺寸来缓存的的。这种方式优点是加载显示非常快。且可以设置缓存图片的尺寸- 默认使用
HttpUrlConnection
下载图片,可以配置为OkHttp
或者Volley
下载,也可以自定义下载方式。 - 默认使用两个线程池来分别执行读取缓存和下载任务,且可以自定义。
- 默认使用手机内置存储进行磁盘缓存,可以配置为外部存储,可以配置缓存大小,图片池大小。
- 在加载同样配置的图片时,
Glide
内存占用更少,因为Glide
是针对每个ImageView
适配图片大小后再存储到磁盘的,这样加载进内存的是压缩过的图片,内存占用自然就比较少。这种做法有助于减少OutOfMemoryError
的出现。 - 高效处理
Bitmap
,使用Bitmap Pool
来对Bitmap
进行复用,主动调用recycle
回收需要回收的Bitmap
,减小系统回收压力
默认情况下Glide
与Picasso
加载同样图片的内存占用比:
配置为ARGB_8888
的情况下Glide
与Picasso
加载同样图片的内存占用比:
With()
方法的比较:
缺点:
- 体积相对来说比较大,目前最新版的大小在
500k
左右 - 当我们从远程
URL
地址下载图片时,Picasso
相比Glide
要快很多。可能的原因是Picasso
下载完图片后直接将整个图片加载进内存,而Glide
还需要针对每个ImageView
的大小来适配压缩下载到的图片,这个过程需要耗费一定的时间。(当然我们可以使用thumbnail()
来减少压缩的时间)
使用简单:
repositories {
mavenCentral()
maven { url 'https://maven.google.com' }
}
dependencies {
compile 'com.github.bumptech.glide:glide:4.1.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.1.1'
}
ImageView imageView = (ImageView) findViewById(R.id.my_image_view);
GlideApp.with(this).load("http://goo.gl/gEgYUd").into(imageView);
由良心公司Square
开源的一款图片加载库。其实他和Glide
很相似,所以一般会与Glide
进行比较。
优点:
- 体积更小,方法数也更少,更轻量。他的库大小及方法数基本是
Glide
的四分之一,目前为120k
左右 - 支持
WebP
- 当我们从远程
URL
地址下载图片时,Picasso
相比Glide
要快很多。可能的原因是Picasso
下载完图片后直接将整个图片加载进内存,而Glide
还需要针对每个ImageView
的大小来适配压缩下载到的图片,这个过程需要耗费一定的时间。(当然我们可以使用thumbnail()
来减少压缩的时间)
缺点:
Picasso
和Glide
在磁盘缓存策略上有很大的不同。Picasso
缓存的是全尺寸的,而Glide
缓存的是跟ImageView
尺寸相同的。Glide
的这种方式优点是加载显示非常快。而Picasso
的方式则因为需要在显示之前重新调整大小而导致一些延迟.- 相对
Glide
来说更耗内存,尤其是加载大一点的图片。同样是因为上面的缓存策略不同。 - 不支持
Gif
图片
使用:
// Picasso
Picasso.with(context)
.load("http://inthecheesefactory.com/uploads/source/glidepicasso/cover.jpg")
.into(ivImg);
// Glide
Glide.with(context)
.load("http://inthecheesefactory.com/uploads/source/glidepicasso/cover.jpg")
.into(ivImg);
- 修改图片大小
// Picasso
.resize(300, 200);
// Glide
.override(300, 200);
- 图片裁剪
// Picasso
.centerCrop();
// Glide
.centerCrop();
- 设置占位图及错误图片
// Picasso
.placeholder(R.drawable.placeholder)
.error(R.drawable.imagenotfound)
// Glide
.placeholder(R.drawable.placeholder)
.error(R.drawable.imagenotfound)
由Facebook
推出,自带光环。
Fresco
中设计有一个叫做Image Pipeline
的模块。它负责从网络,从本地文件系统,本地资源加载图片。为了最大限度节省空间和CPU时间,它含有3级缓存设计(2级内存,1级磁盘)。Fresco
中设计有一个叫做Drawees
模块,它会在图片加载完成前显示占位图,加载成功后自动替换为目标图片。当图片不再显示在屏幕上时,它会及时地释放内存和空间占用。- 如果仅用基本的图片加载功能的话,大小仅为
20k
左右 - 解压后的图片,即
Android
中的Bitmap
,占用大量的内存。大的内存占用势必引发更加频繁的GC
。在5.0
以下,GC
将会显著地引发界面卡顿。 在5.0
以下系统,Fresco
将图片放到一个特别的内存区域。当然,在图片不显示的时候,占用的内存会自动被释放。这会使得APP
更加流畅,减少因图片内存占用而引发的OOM
。Fresco
在低端机器上表现一样出色,你再也不用因图片内存占用而思前想后。 - 渐进式的
JPEG
图片格式已经流行数年了,渐进式图片格式先呈现大致的图片轮廓,然后随着图片下载的继续,呈现逐渐清晰的图片,这对于移动设备,尤其是慢网络有极大的利好,可带来更好的用户体验。Android
本身的图片库不支持此格式,但是Fresco
支持。使用时,和往常一样,仅仅需要提供一个图片的URI
即可,剩下的事情,Fresco
会处理。 - 图片可以在任意点进行裁剪,而不是中心,即自定义居中焦点。
JPEG
可以在native
进行resize
,避免了在缩小图片时的OOM
风险。- 支持
Gif
图片。 - 支持
WebP
。 - 内存管理,三级缓存设计
- 图片预览,渐进式显示效果和多图请求
- 第一次加载和加载缓存速度都比较快
- 下载失败之后,点击重现下载
- 自定义占位图,自定义
overlay
, 或者进度条 - 先显示一个低解析度的图片,等高清图下载完之后再显示高清图
- 对于本地图,如有EXIF缩略图,在大图加载完成之前,可先显示缩略图
- 缩放或者旋转图片
Fresco
和Glide
在内存占用上,Fresco
更优,这是由于Fresco
将图片放置到一块特殊的Native
内存,这块内存的管理是由Fresco
进行的,所以Fresco
的体积比较庞大,会为应用增加接近2M
的体积,这算是Fresco
的一个缺点.
缺点:
- 他也是一个非常优秀的项目,由于
Fresco
的设计需要使用DraweeView
替代ImageView
所以我个人来说没有选择它, - 由于其缓存特性,会导致应用的体积变大。
使用:
- 必备功能
dependencies {
// your app's other dependencies
compile 'com.facebook.fresco:fresco:1.5.0'
}
- 可选功能
dependencies {
// For animated GIF support
compile 'com.facebook.fresco:animated-gif:1.5.0'
// For WebP support, including animated WebP
compile 'com.facebook.fresco:animated-webp:1.5.0'
compile 'com.facebook.fresco:webpsupport:1.5.0'
// For WebP support, without animations
compile 'com.facebook.fresco:webpsupport:1.5.0'
// Provide the Android support library (you might already have this or a similar dependency)
compile 'com.android.support:support-core-utils:24.2.1'
}
- 初始化:
[MyApplication.java]
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Fresco.initialize(this);
}
}
- 创建布局文件:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
>
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/my_image_view"
android:layout_width="130dp"
android:layout_height="130dp"
fresco:placeholderImage="@drawable/my_drawable"
/>
</LinearLayout>
- 代码使用:
Uri uri = Uri.parse("https://raw.githubusercontent.com/facebook/fresco/master/docs/static/logo.png");
SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);
draweeView.setImageURI(uri);
综上所述:对我来说Glide
是最合适的。
- 邮箱 :charon.chui@gmail.com
- Good Luck!