Picasso
Posted 劲火星空
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Picasso相关的知识,希望对你有一定的参考价值。
一、例子
直接上代码
如下就是Picasso最简单的例子,我们在使用的时候就是这么简单,直接with、load、into
// 普通加载图片
Picasso.with(PicassoActivity.this)
.load("http://n.sinaimg.cn/translate/20160819/9BpA-fxvcsrn8627957.jpg")
.into(ivPicassoResult1);
// 裁剪的方式加载图片
Picasso.with(PicassoActivity.this)
.load("http://n.sinaimg.cn/translate/20160819/9BpA-fxvcsrn8627957.jpg")
.resize(100,100)
.into(ivPicassoResult2);
// 选择180度
Picasso.with(PicassoActivity.this)
.load("http://n.sinaimg.cn/translate/20160819/9BpA-fxvcsrn8627957.jpg")
.rotate(180)
.into(ivPicassoResult3);
二、原理
首先来看三个函数,第一个是with函数,很显然使用的是单例模式和Builder模式,然后创建一个Picasso的实例
public static Picasso with(Context context)
if (singleton == null)
synchronized (Picasso.class)
if (singleton == null)
singleton = new Builder(context).build();
return singleton;
然后load函数,这个有好几个,分别针对的是不同的资源类型
public RequestCreator load(Uri uri)
...
public RequestCreator load(String path)
...
public RequestCreator load(int resourceId)
...
最后是into函数,这个函数还是比较复杂的一个函数
public void into(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.");
if (!data.hasImage())
picasso.cancelRequest(target);
target.onPrepareLoad(setPlaceholder ? getPlaceholderDrawable() : null);
return;
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);
这里最主要的就是创建一个Reques对象,我们前面做的一些封装和设置都会封装到这个Request对象中
检查我们要显示的图片是否可以直接在缓存中获取,如果有就直接显示出来好了。
缓存没命中,那就只能费点事把源图片down下来了。这个过程是异步的,并且通过一个Action来完成请求前后的衔接工作。
首先进行参数的设置,然后创建request请求对象,最后通过通过action来进行图片的请求。
1. 首先看一下构造函数
Picasso(Context context, Dispatcher dispatcher, Cache cache, Listener listener,
RequestTransformer requestTransformer, List<RequestHandler> extraRequestHandlers, Stats stats,
Bitmap.Config defaultBitmapConfig, boolean indicatorsEnabled, boolean loggingEnabled)
...
我们是通过单例和建造者模式来完成实例化的,在build的过程中向picasso中传递这些参数,自己来灵活的定制
2、看一build函数中的代码是什么样子
public Picasso build()
Context context = this.context;
if (downloader == null)
downloader = Utils.createDefaultDownloader(context);
if (cache == null)
cache = new LruCache(context);
if (service == null)
service = new PicassoExecutorService();
if (transformer == null)
transformer = RequestTransformer.IDENTITY;
Stats stats = new Stats(cache);
Dispatcher dispatcher = new Dispatcher(context, service, HANDLER, downloader, cache, stats);
return new Picasso(context, dispatcher, cache, listener, transformer, requestHandlers, stats,
defaultBitmapConfig, indicatorsEnabled, loggingEnabled);
Downloader:它是一个接口,规定了一些通用的方法,这也就意味着,我们可以提供自己的下载器
Cache:Picasso的缓存,这里实例化的是LruCache,其内部使用的是LinkedHashMap
ExecutorService:这里Picasso实现了自己的PicassoExecutorService,它继承了ThreadPoolExecutor,也就是Picasso自己维护了一个线程池,用于异步加载图片。
Stats:这个类只要是维护图片的一些状态Dispatcher:从名字上就可以判断出来,这个类在这里起到了一个调度器的作用,图片要不要开始下载以及下载后Bitmap的返回都是通过这个调度器来执行的
3、也是通过异步请求的方式来进行的
上面的into方法中中最终会创建一个action,这个action里边包含picasso对象、目标和Request请求等
然后会调用enqueueAndSubmit方法,而最终是调用了Dispatcher的dispatchSubmit方法,也就是我们前面说的,Dispatcher起到了调度器的作用。在Dispatcher内部,Dispatcher定义了DispatcherThread和DispatcherHandler两个内部类,并在Dispatcher的构造函数中对他们经行了实例化,所有的调度也都是通过handler异步的执行的,如下是Dispatcher
Dispatcher(Context context, ExecutorService service, Handler mainThreadHandler,
Downloader downloader, Cache cache, Stats stats)
this.dispatcherThread = new DispatcherThread();
this.dispatcherThread.start();
...
this.handler = new DispatcherHandler(dispatcherThread.getLooper(), this);
...
构建实例之后建立一个
BitmapHunter类来进行图片的加载,这个类也是继承Runnable接口的类,加载完成图片之后怎么去进行进行主线程的更新是个问题
4、进行图片的主线程跟新操作
因为是异步的,最终也是通过消息机制来进行发送的,同message的方式发送到主线程中进行图片的渲染和更新的操作
Picasso并不是立即将图片显示出来,而是用到了一个批处理,其实就是把操作先暂存在一个list中,等空闲的时候再拿出来处理,这样做得好处也是尽量减少主线程的执行时间,一方面防止ANR,另一方面快速返回,响应页面的其他渲染操作,防止卡顿用户界面。
private void batch(BitmapHunter hunter)
if (hunter.isCancelled())
return;
batch.add(hunter);
if (!handler.hasMessages(HUNTER_DELAY_NEXT_BATCH))
handler.sendEmptyMessageDelayed(HUNTER_DELAY_NEXT_BATCH, BATCH_DELAY);
尊重作者,尊重原创,参考文章:
http://www.jianshu.com/p/459c8ca3f337
以上是关于Picasso的主要内容,如果未能解决你的问题,请参考以下文章