Picasso学习
来源:互联网 发布:陕西大数据集团胡刚 编辑:程序博客网 时间:2024/06/09 16:57
简介:
Picasso是Square公司开源的一个Android图形缓存库。可以实现图片下载和缓存功能。
文档地址:http://square.github.io/picasso/2.x/picasso/;
下载地址:http://square.github.io/picasso/#download
特点:
1.加载载网络或本地图片并自动缓存处理;
2.链式调用;
3.图形转换操作,如变换大小,旋转等,提供了接口来让用户可以自定义转换操作;
4.在Adapter中回收和取消当前的下载功能;
与Universal-ImageLoader库对比:
1.都有高效的网络图片下载和缓存性能;
2.Universal-ImageLoader功能多,灵活使用配置;
3.Picasso使用复杂的图片压缩转换来尽可能的减少内存消耗;
4.在Adapter中需要取消已经不在视野范围的ImageView图片资源的加载,否则会导致图片错位,Picasso已经解决了这个问题;
用法:
(1)Picasso.with(context).load(url).into(imageView);(2)Picasso.with(context).load(url).resize(50,50).centerCrop().placehold er(holderUrl).error(errorUrl).into(imageView);
Resize(x,y):重新设置图片尺寸;
centerCrop():scaleType设置为centerCrop;
rotate(degrees):旋转图片;
除了加载网络图片,picasso还支持加载Resources,assets, files, content providers中的本地资源文件
流程图:
流程总结:当执行Picasso.with(context).load(url).into(imagevi)时,会首先构造Picasso实例,然后会根据url创建请求(Request,Action),将请求交给Dispatcher,Dispatcher再在子线程对请求任务进行调度,将请求任务交给线程池(ExecutorService),执行完毕后,将结果传给主线程的handler,最后在主线程中将图片设置到ImageView上。
关键类分析:
Picasso:
负责图片下载、转换和缓存的管理。
Picasso.with(context)采用单例模式+双重锁定模式创建Picasso实例:
public staticPicassowith(Context context) {
if (singleton==null) {
synchronized (Picasso.class) {
if (singleton==null) {
singleton =newBuilder(context).build();
}
}
}
return singleton;
}
Request::
Request表示一个任务请求,记录所有对图形的操作,供之后图形的创建使用(如resize,rotate)。还可以实现接口Transformation,进行自定义图形变换。
RequstCreator:
负责生成Request对象,into()方法是加载图片的入口。
public voidinto(Target target){
long started = System.nanoTime();
checkMain();//检查是否是主线程
if (target ==null) {
throw new IllegalArgumentException("Target must not be null.");
}
if (deferred) {
throw new IllegalStateException("Fit cannot be used with a Target.");
}
//判断ImageView是否正确
if (!data.hasImage()) {
picasso.cancelRequest(target);
target.onPrepareLoad(setPlaceholder? getPlaceholderDrawable() :null);
return;
}
//创建Request对象
Request request = createRequest(started);
String requestKey = createKey(request);
//判断缓存是否有图片
if (shouldReadFromMemoryCache(memoryPolicy)) {
Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey);
if (bitmap != null) {
picasso.cancelRequest(target);
target.onBitmapLoaded(bitmap,MEMORY);
return;
}
}
target.onPrepareLoad(setPlaceholder ?getPlaceholderDrawable() :null);
Action action =
new TargetAction(picasso,target,request,memoryPolicy,networkPolicy,errorDrawable,
requestKey,tag,errorResId);
picasso.enqueueAndSubmit(action);//提交请求任务Action
}
Action:
Action代表一个具体的加载任务,主要用于图片加载后的结果回调。
ImageViewAction实现了Action的两个抽象方法:complete()和error()。Complete()将bitmap设置给imageView,并回调callback.onSuccess();error()将errorDrawable设置给ImageView,并回调callback.onError()。
public voidcomplete(Bitmap result,Picasso.LoadedFromfrom) {
…
//把bitmap加載到ImageView上
Context context = picasso.context;
boolean indicatorsEnabled = picasso.indicatorsEnabled;
PicassoDrawable.setBitmap(target,context,result,from,noFade,indicatorsEnabled);
//回調callback.onSuccess()
if (callback!=null) {
callback.onSuccess();
}
}
Action有个需要关注的点,那就是WeakReference target,它持有的是Target(比如ImageView ..)的弱引用,这样可以保证加载时间很长的情况下也不会影响到Target的回收了。
BitmapHunter:
实现了Runnable接口,通过PicassoExecutorService.submit(Runnable)把bitmapHunter对象添加到工作线程任务队列,获取并上传目标图片(dispatcher.dispatchComplete(this))。
Hunt(){
…
//加载图片
data.networkPolicy=retryCount==0? NetworkPolicy.OFFLINE.index:networkPolicy;
RequestHandler.Result result = requestHandler.load(data,networkPolicy,picasso.byteArrayPool);
…
}
假设从网络取值,查看NetworkRequestHandler.load():
public Result load(Request request, intnetworkPolicy,ByteArrayPool byteArrayPool) throwsIOException {
//利用downloader下载图片数据,downloader是创建Dispatcher时传进来的
Response response = downloader.load(request.uri,request.networkPolicy);
if (response == null) {
return null;
}
//判断是从缓存取还是从网络取
Picasso.LoadedFrom loadedFrom = response.cached?DISK:NETWORK;
Bitmap bitmap = response.getBitmap();
if (bitmap != null) {
return new Result(bitmap,loadedFrom);
}
//如果是从网络返回的,那么拿到的是流对象
InputStream is = response.getInputStream();
if (is == null) {
return null;
}
// Sometimes response content length is zero when requests are beingreplayed. Haven't found
// root cause to this but retrying therequest seems safe to do so.
if (loadedFrom ==DISK&&response.getContentLength() ==0) {
Utils.closeQuietly(is);
throw new ContentLengthException("Receivedresponse with 0 content-length header.");
}
if (loadedFrom ==NETWORK&&response.getContentLength() >0) {
stats.dispatchDownloadFinished(response.getContentLength());
}
MarkableInputStream markStream = new MarkableInputStream(is);
long mark = markStream.savePosition(65536);//TODO fix thiscrap.
int orientation =newImageHeaderParser(markStream,byteArrayPool).getOrientation();
markStream.reset(mark);
//将结果封装返回
return new Result(null,markStream,loadedFrom,orientation);
}
Dispatcher:
是整个图片加载过程的任务调度器。外部调用dispatchXXX()方法,然后通过handler将请求转换为调用对于的performXXX()。
void performSubmit(Action action, booleandismissFailed){
…
//生成bitmapHunter,其中遍历requestHandlers,通过requestHandler.canHandleRequest(request)匹配合适的RequestHandler子类
hunter = forRequest(action.getPicasso(), this,cache,stats,action);
//将hunter任务加入到工作线程任务栈,并获取future返回
hunter.future=service.submit(hunter);
hunterMap.put(action.getKey(),hunter);
…
}
Cache:
实现图片的缓存。LruCache实现了Cache接口,存储的结构采用了LinkedHashMap,这种map内部实现了lru算法(Least Recently Used 近期最少使用算法)。主要是set()和get()方法,图片下载完成后,在dispatcher.performComplete()会调用set()方法。而在requestCreator.into(),bitmapHunter.hunt()会通过shouldReadFromMemoryCache(memoryPolicy)检查是否可以从缓存获取图片,如果可以则调用get()方法。
附:
Tansformation 的实现例子,实现圆形图片显示。
import android.graphics.Bitmap;import android.graphics.BitmapShader;import android.graphics.Canvas;import android.graphics.Paint;import com.squareup.picasso.Transformation;public class CircleTransform implements Transformation { @Override public Bitmap transform(Bitmap source) { int size = Math.min(source.getWidth(), source.getHeight()); int x = (source.getWidth() - size) / 2; int y = (source.getHeight() - size) / 2; Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size); if (squaredBitmap != source) { source.recycle(); } Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig()); Canvas canvas = new Canvas(bitmap); Paint paint = new Paint(); BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP); paint.setShader(shader); paint.setAntiAlias(true); float r = size / 2f; canvas.drawCircle(r, r, r, paint); squaredBitmap.recycle(); return bitmap; } @Override public String key() { return "circle"; }}
参考文档:http://www.2cto.com/kf/201511/451087.html
- Picasso学习
- Picasso学习笔记
- Picasso学习笔记
- Glide VS Picasso 学习
- Picasso源码学习
- picasso学习笔记
- 学习Picasso(毕加索)
- 《Picasso源码学习》
- Picasso源码学习
- Picasso学习笔记
- Picasso 图片框架的学习
- Picasso(毕加索)框架 学习笔记
- Picasso使用学习(一)
- Picasso使用学习(二)
- Picasso
- Picasso
- Picasso
- picasso
- Intent详解(四):使用隐式Intent
- linux tcpdump的简单应用
- IOS之导航控制器
- Android 四种加载方式详解(standard、singleTop、singleTask、singleInstance)
- 电脑上的快捷键
- Picasso学习
- MySQL损坏表修复(附录自动处理脚本)
- 遍历UltraWebGrid获得rows 及 从行中取出列值
- ViewPager跟FragmentTabHost结合起来使用
- 欢迎使用CSDN-markdown编辑器
- ubuntu14.04经典桌面怎么删除启动器的快捷方式
- linux内核里的GPIO操作函数
- 【Android基础学习】Listview的倒序显示问题
- android学习笔记--sqlite数据库