Picasso
picasso是Square公司开源的一个Android图形缓存库,可以实现图片下载和缓存功能。Picasso不仅实现了图片异步加载的功能,还解决了android中加载图片时需要解决的一些常见问题:
1.在adapter中需要取消已经不在视野范围的ImageView图片资源的加载,否则会导致图片错位,Picasso已经解决了这个问题。
2.使用复杂的图片压缩转换来尽可能的减少内存消耗
3.自带内存和硬盘二级缓存功能
4、Picasso还提供了debug的标示,设置为true,他会明确标示出图片是从内存加载还是从本地磁盘或者是网络加载过来。
5、用最小的内存去处理复杂的图片转换。比如图片要处理图片为圆形图片,图片要旋转一个角度等。都可以通过一个代码来帮助你完成。
使用简介
首先在项目中引入picasso:
compile 'com.squareup.picasso:picasso:2.5.2'
ImageVIew设置图片
Picasso.with(context).load(url). into(imageView);
短短的一行代码为我们解决了很多问题:自动将图像缓存在本地通过图片压缩转换以减少内存消耗自动处理了ImageView的回收,即自动取消不在视野范围内的ImageView视图资源的加载;
自定义的布局设置图片,target是指实现了Target接口的自定义View
Picasso.with(context).load(url).placeholder(R.drawable.tab_item_bg).into(target);
adapter中的使用:
//View复用会自动察觉并且取消之前的下载任务
@Override
public void getView(int position, View convertView, ViewGroup parent) {
SquaredImageView view = (SquaredImageView) convertView;
if (view == null) {
view = new SquaredImageView(context);
}
String url = getItem(position);
Picasso.with(context).load(url).into(view);
}
自动设置图片宽高像素的大小:
Picasso.with(context) .load(url) .resize(50, 50) .centerCrop() .into(imageView)
占位符图片:
Picasso.wint(context).load(imageUrl).placeholder(R.drawable.image_placeholder).error(R.drawable.image_error);
所谓的占位符图像即当图片未正常显示时默认的图片,通过placeholder()设置,Picasso也支持设置图片显示错误时显示的默认图片,通过error()设置.
载入本地资源:除了通过网络下载图片,Picasso也可以载入本地图片资源:
Picasso.with(context).load(R.drawable.icon).into(imageView);
Picasso.with(context).load("file:///android_asset/Adnroid.png").into(imageView);
Picasso.wiht(context).load(new File(...)).into(imageView);
调试:为了方便调试,你可以通过调用Picasso的setIndicatiorEnabled(true);可以让不同来源的图片显示一个不同的色彩标记。
整体架构:
Picasso类是一个负责图片下载、变换、缓存的管理器,当它收到一个图片下载请求的时候,它会创建Request并提交给Dispatcher,Dispatcher会寻找对应的处理器RequestHandler,并将请求与该处理器一起提交给线程池执行,图片获取成功后,最终会交给PicassoDrawable显示到Target上。
它将一张图片的加载过程分为八步,依次为:
创建->入队->执行->解码->变换->批处理->完成->分发->显示(可选)
简单总结下,当我们执行Picasso.with(context).load(url).into(imageview)时,首先会构造Picasso实例,然后会根据url创建请求,然后请求会被交给Dispatcher,Dispatcher将在子线程对请求任务进行调度,将请求任务交给线程池执行,执行完毕后,将结果传给主线程的handler,最后在主线程中将图片设置到ImageView上.
关于缓存策略:
Picasso的缓存是内存缓存+磁盘缓存,内存缓存基于LruCache类,可配置替换。磁盘缓存依赖于http缓存,不可配置。先看内存缓存.内存缓存比较简单,是通过LinkedHashMap实现.读缓存时机:生成了请求Request对象,准备创建Action加载任务之前,会先去缓存里面查找下.
写缓存时机:图片从网络或者其他地方加载成功后,即在BitmapHunter的run方法执行结束的时候.Dispatcher#performComplete
if (shouldWriteToMemoryCache(hunter.getMemoryPolicy())) {
cache.set(hunter.getKey(), hunter.getResult());
}
注意,缓存的是经过压缩之后的图片(如果你使用了fit或者resize方法的话),
再看磁盘缓存。如果你是使用UrlConnectionDownloader的话,那很不幸,缓存只在Api>14上生效,因为缓存依赖于HttpResponseCache.如果你依赖了okhttp,那么缓存策略始终是有效的。另外需要说明的是,既然是http缓存,那么缓存的可用性依赖于http响应是否允许缓存,也就是说得看响应中是否携带Cache-Control、Expires等字段.
关于图形变换
图形变换在Picasso中被抽象成Transformation接口,具体的变换操作由transform方法实现.Request维护一个图形变换的列表List,当图片加载成功后,BitmapHunter中将会遍历这个变换集合,依次进行变换,最后返回变换后的bitmap.恩,其实是一个回调的思想,将操作封装到接口中交给系统,系统在某个特定时机调用你的接口。
关于CleanupThread
Picasso类中有一个内部线程叫CleanupThread,这是一个daemon线程,它的工作是找到那些Target(比如说ImageView)已经被回收
但是所对应的Request请求还在继续的任务(Action),找到之后,会取消对应的请求,避免资源浪费.
图片压缩
图片压缩的原理通常都是利用BitmapFactory#Options类,先将injustDecodeBounds设置为true,对Bitmap进行一次解码,拿到outWidth/outHeight,即实际宽高,然后根据期望压缩到的宽和高算出inSampleSize,最后将injustDecodeBounds设置为false,再对Bitmap进行一次解码即可。另一种压缩的方法是设置图片的显示效果,比如ARGB_8888可以把它设置为占用四个字节的ARGB_4444,等等.Picasso综合了利用这两种方案.