图片库 | Picasso | Glide |
---|---|---|
版本 | 2.5.2 | 3.7.0 |
作者 | square | bumptech |
时间 | 2012 | 2013 |
star | 12k | 12k |
大小 | 121KB | 476KB |
方法数 | 849 | 2879 |
还以这张老图为例:
大小739*417,32位色,全大小RBG_8888时占用内存约1203KB
导入图片库
Picasso:
compile 'com.squareup.picasso:picasso:2.5.2'
Glide:
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.android.support:support-v4:19.1.0'
现在v7(依赖v4)包基本上是标配,所以不一般不用再显式引入v4包
Java代码
Picasso:
Picasso.with(this).load(URL).into(ivPicasso);
Glide:
Glide.with(this).load(URL).into(ivGlide);
代码看上去差不多
最后因为我们加载的是网络上的图片,别忘了添加权限
<uses-permission android:name="android.permission.INTERNET"/>
ps:我的两个ImageView是相同的固定尺寸,并且比原图小
看一下效果吧:
看出有什么差别了么
使用简单
都可以通过一句代码可实现图片获取和显示。
都支持webp格式的图片
http://zhitu.isux.us/assets/img/imgSample/test-60.webp
内存缓存
默认都是LruCache 开启,都可以设置不使用内存缓存,如下
Glide:
Glide.with( context )
.load( URL )
.skipMemoryCache( true )
.into( ivGlide);
ps:如果第一次某个url时候没有skipMemoryCache( true ),后面带上了图片还是会被缓存到内存中
Picasso:
Picasso.with(this).
load(URL).
memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE).
into(ivPicasso);
MemoryPolicy.NO_CACHE:不从内存缓存中查找
MemoryPolicy.NO_STORE:不存储到内存缓存中
指定加载进内存的图片尺寸
Picasso:
.resize(300, 200);
Glide:
.override(300, 200);
CenterCrop
都用:
.centerCrop();
变换
Picasso:
.transform(new CircleTransform())
Glide:
.transform(new CircleTransform(context))
在返回前对图片做一些处理工作
设置默认占位图和错误占位图
.placeholder(R.drawable.placeholder)
.error(R.drawable.imagenotfound)
优先级
.priority()
如App 页面中 Banner 的优先级高于 Icon 时就很适用
支持多种数据源
支持多种数据源,网络、本地、资源、Assets 等
支持多种 Displayer
不仅仅支持 ImageView,同时支持自定义Target
默认的Bitmap格式
上面的图可以看出来Glide加载出来的图片质量是比Picasso差的,这是因为Picasso加载Bitmap的格式是RGB_8888,Glide默认Bitmap的格式是RGB_565;这也就是说Picasso每个像素只用四个字节,而Glide每个像素用两个字节,占用内存减少一半,差的图片质量对应低内存占用。
下面是在内存快照中找到的对应图片在内存中的大小:
Picasso:1232652字节,约1203KB
发现Glide所占的内存不是Picasoo的一半,居然更少。
可以通过自定义Module来让Glide加载ARGB_8888格式的图片,这看实际的需求吧。
默认加载到内存的图片大小
Picasso不管ImageView的大小都会加载全尺寸的图片到内存中,让GPU来重绘大小。而Glide会根据ImageView的大小来加载不同尺寸的图片到内存中。这时当ImageView的大小比原图小很多的时候,Glide的优势就会非常的明显。
其实Picasso也能实现相应的功能,只是显得比较笨拙。
Picasso.with(this).load(URL).fit().into(ivPicasso);
发现大约是两倍,这就对了
Picasso.with(this).load(URL).resize(400,230).into(ivPicasso);
这样导致的问题是,我们需要自己手动计算出ImageView的大小
ps:这里必须说明的一个问题是,Glide在wrap_content的情况下加载一个全大小的图片进入内存。
硬盘缓存
Picasso:
我分别在xml指定ImageView 为400px *230px 和 200px *130px ,让Picasso来加载同一张图片,然候查看缓存
额,发现三个文件最大的那个是图片本身,是全尺寸的,另外一个存的是这张图片对应的HTTP响应头,journal是DiskLruCache的日志文件。
其实重点是只缓存了一个全尺寸的的图片,但是同时也验证了Picasso的缓存是借助于okhttp实现的。
Glide:
进行同样的操作:
发现也是有三个文件,但是这其中两个都是图片,尺寸和之前加载的图片大小都相同,journal同样是DisLruCache的日志文件。也就是说默认情况Glide为每种尺寸的ImageView都缓存一次。
Glide这样做的好处是加载显示非常快,而Picasso需要在显示之前重新调整图片的大小,导致有一些延迟
另外,Glide也支持其他的硬盘缓存策略:
DiskCacheStrategy.SOURCE
只缓存原始大小的图片,和Picasso一样
DiskCacheStrategy.RESULT
默认的缓存策略,只缓存经过压缩后的图片,不缓存原始的图片;这种情况下每有一种尺寸的ImageView都要从网络重新下载,即使后来ImageView的尺寸比之前小。
DiskCacheStrategy.ALL caches all versions of the image
缓存所有的图片,包括原始的和各种尺寸的图片。下载全尺寸的图片,以后不需要再从网络下载,只需要对原始的图片调整成合适的大小,然后再缓存。
Glide.with(this).load(URL).diskCacheStrategy(DiskCacheStrategy.ALL).into(ivGlide);
并发线程数改变策略
Picasso:
根据网络类型的切换来改变线程数
//class PicassoExecutorService
void adjustThreadCount(NetworkInfo info) {
if (info == null || !info.isConnectedOrConnecting()) {
setThreadCount(DEFAULT_THREAD_COUNT);
return;
}
switch (info.getType()) {
case ConnectivityManager.TYPE_WIFI:
case ConnectivityManager.TYPE_WIMAX:
case ConnectivityManager.TYPE_ETHERNET:
setThreadCount(4);
break;
case ConnectivityManager.TYPE_MOBILE:
switch (info.getSubtype()) {
case TelephonyManager.NETWORK_TYPE_LTE: // 4G
case TelephonyManager.NETWORK_TYPE_HSPAP:
case TelephonyManager.NETWORK_TYPE_EHRPD:
setThreadCount(3);
break;
case TelephonyManager.NETWORK_TYPE_UMTS: // 3G
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
setThreadCount(2);
break;
case TelephonyManager.NETWORK_TYPE_GPRS: // 2G
case TelephonyManager.NETWORK_TYPE_EDGE:
setThreadCount(1);
break;
default:
setThreadCount(DEFAULT_THREAD_COUNT);
}
break;
default:
setThreadCount(DEFAULT_THREAD_COUNT);
}
}
Glide:
根据CPU的核数
//class GldieExecutor
public static int calculateBestThreadCount() {
// We override the current ThreadPolicy to allow disk reads.
// This shouldn't actually do disk-IO and accesses a device file.
// See: https://github.com/bumptech/glide/issues/1170
ThreadPolicy originalPolicy = StrictMode.allowThreadDiskReads();
File[] cpus = null;
try {
File cpuInfo = new File(CPU_LOCATION);
final Pattern cpuNamePattern = Pattern.compile(CPU_NAME_REGEX);
cpus = cpuInfo.listFiles(new FilenameFilter() {
@Override
public boolean accept(File file, String s) {
return cpuNamePattern.matcher(s).matches();
}
});
} catch (Throwable t) {
if (Log.isLoggable(TAG, Log.ERROR)) {
Log.e(TAG, "Failed to calculate accurate cpu count", t);
}
} finally {
StrictMode.setThreadPolicy(originalPolicy);
}
int cpuCount = cpus != null ? cpus.length : 0;
int availableProcessors = Math.max(1, Runtime.getRuntime().availableProcessors());
return Math.min(MAXIMUM_AUTOMATIC_THREAD_COUNT, Math.max(availableProcessors, cpuCount));
}
图片加载会和Activity和Fragment的生命周期保持一致
Glide.with()函数除了支持Context外,还支持Fragment和Activity,如在onPause后暂停加载,在onResume后恢复加载
载Gif动画
加载视频
这个支持本地视频,可以将本地视频的第一帧解码成一张静态图片。
缩略图
配置图片显示的动画
Picasso只有一种动画:fading in