摘要
分析Picasso加载图片的流程。以以下代码为主线分析。
|
|
根据自己写的Test页面,通过picasso以下加载方式,
|
|
分析picasso加载图片的流程。
缺少的内容:
- 默认7种RequestHandler并没有具体分析,对于NetworkRequestHandler应该是分析的重点,因为还涉及到网络库OkHttp的使用;
- Cache相关;
- 等
对于流程图没有说清楚的补充说明:
加载图片的方式:
加载一张图片
1Picasso.with(this).load("url").placeholder(R.mipmap.ic_default).into(imageView);加载一张图片并设置一个回调接口
12345678Picasso.with(this).load("url").placeholder(R.mipmap.ic_default).into(imageview, new Callback() {public void onSuccess() {}public void onError() {}});同步加载一张图片,注意只能在子线程中调用并且Bitmap不会被缓存到内存里
12345678910111213141516new Thread() {public void run() {try {final Bitmap bitmap = Picasso.with(getApplicationContext()).load("url").get();mHandler.post(new Runnable() {public void run() {imageView.setImageBitmap(bitmap);}});} catch (IOException e) {e.printStackTrace();}}}.start();加载一张图片并设置tag,可以通过tag来暂定或者继续加载,可以用于当ListView滚动是暂定加载,停止滚动恢复加载
123Picasso.with(this).load("url").tag(mContext).into(imageView);Picasso.with(this).pauseTag(mContext);Picasso.with(this).resumeTag(mContxt);加载一张图片并自适应imageView的大小,如果imageView设置了wrap_content,会显示不出来,直到该ImageView的LayoutParams被设置而且调用了该View的ViewTreeObserver.OnPreDrawListener回调接口后才会显示
1Picasso.with(this).load("url").fit().into(imageView);加载一张图片并按照指定尺寸以centerInside()的形式缩放,并设置加载的优先级为高。注意centerInside()或centerCrop()只能同时使用一种,而且必须指定resize()或者resizeDimen()
1Picasso.with(this).load("url").resize(400,400).centerInside().priority(Picasso.Priority.HIGH).into(imageView);加载一张图片旋转并且添加一个Transformation,可以对图片进行各种变化处理,例如圆形头像.
1234567891011Picasso.with(this).load("url").rotate(10).transform(new Transformation() {public Bitmap transform(Bitmap source) {//处理Bitmapreturn null;}public String key() {return null;}}).into(imageView);
注释的补充说明:
new Picasso.Builder(context)#build()方法里
PicassoExecutorService默认有3个执行线程,corePoolSize=maximumPoolSize=3,会根据网络状况自动切换线程数;
除了添加可以自定义的extraRequestHandlers,另外默认添加了7个RequestHandler分别用来处理加载不同来源的资源,可能是Resource里的,也可能是File,也可能是来源于网络的资源;
在调用into()方法之前,所有的操作都是在设定我们需要处理的参数,真正的操作都是有into()方法引起的;
deferred=true表示fit()模式,即表示延时加载,fit()模式是适应target的宽高加载,所以并不能手动设置resize,如果设置就抛出异常;和加载图片方式中6不同;
1picasso.defer(target, new DeferredRequestCreator(this, target, callback));
该方法监听ImageView的ViewTreeObserver.OnPreDrawListener接口,一旦ImageView的宽高被赋值,就按照ImageView的宽高继续加载;
- Picasso#complete(BitmapHunter hunter) -> Picasso#deliverAction(Bitmap result, LoadedFrom from, Action action) -> action#complete(Bitmap result, Picasso.LoadedFrom from)在这个流程中,我们在RequestCreator#into(ImageView target, Callback callback)方法中创建的是ImageAction,所以最终调用到ImageAction#complete(Bitmap result, Picasso.LoadedFrom from)的方法中。通过了PicassoDrawable.setBitmap()将Bitmap设置到ImageView上,最后并回调callback接口,这里使用PicassoDrawabl来设置Bitmap是因为Picasso自带渐变的加载动画,这里就是处理渐变动画的地方。
Picasso的缓存逻辑:
LruCache(使用LinkedHashMap实现,和android.util.LruCache中的实现类似)是基于内存的缓存,硬盘缓存的控制在OkHttp中,具体使用DiskLruCache
- 加载图片的url及图片属性在内存缓存中存在,如果存在读取内存
- 如果不命中内存缓存,加载图片到disk硬盘缓存和memory内存缓存中
- 内存和硬盘缓存相互独立
个人评价:
Picasso代码量小,维护起来比较方便,但扩展性比较弱,也没有Gif支持。