标签:
picasso的使用非常简单。我们只需要一行代码就够
picasso.with(context).load(uri).into(imageView);
先看with方法
public static Picasso with(Context context) { if (singleton == null) { synchronized (Picasso.class) { if (singleton == null) { singleton = new Builder(context).build(); } } } return singleton; }
这里使用了单例模式,而且是双重检测锁的方法。 另外还使用到了Builder模式,因为Picasso对象的创建非常复杂
我们直接看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(这里使用的LRU算法),PicassoExecutorService(这是Picasso自己实现的线程池),Transformer(当请求被submit时可以调用他去修改请求)。
接下来是Stats stats = new Stats(cache).
可以看下这里类里面的主要的成员变量
final HandlerThread statsThread; final Cache cache; final Handler handler; long cacheHits; long cacheMisses; long totalDownloadSize; long totalOriginalBitmapSize; long totalTransformedBitmapSize; long averageDownloadSize; long averageOriginalBitmapSize; long averageTransformedBitmapSize; int downloadCount; int originalBitmapCount; int transformedBitmapCount;
主要为了记录一些缓存的命中次数,下载的文件大小,下载次数,原始文件大小等等信息,暂时先不看是干什么用的
这里有一个Handler,是做什么用的呢?比如Picasso请求一个之前已经请求过,现在已经被缓存过的图片,这时候在访问它就是命中了,这时候可以调用 stats.dispatchCacheHit();
void dispatchCacheHit() { handler.sendEmptyMessage(CACHE_HIT); }
@Override public void handleMessage(final Message msg) { switch (msg.what) { case CACHE_HIT: stats.performCacheHit(); break; case CACHE_MISS: stats.performCacheMiss(); break; case BITMAP_DECODE_FINISHED: stats.performBitmapDecoded(msg.arg1); break; case BITMAP_TRANSFORMED_FINISHED: stats.performBitmapTransformed(msg.arg1); break; case DOWNLOAD_FINISHED: stats.performDownloadFinished((Long) msg.obj); break; default: Picasso.HANDLER.post(new Runnable() { @Override public void run() { throw new AssertionError("Unhandled stats message." + msg.what); } }); } }
就执行了performCacheHit方法,即cacheHits++
这里为什么绕了一个大弯子,picasso先是调用stats.dispatchCacheHit().该方法里通过handler发送一个消息,然后接收到消息后,把cacheHits++。为什么不直接在dispatchCacheHit方法里cacheHits++。比如像downloadCount,totalDownloadSize等成员变量就是直接++的。
build()里还有一行Dispatcher dispatcher = new Dispatcher(context, service, HANDLER, downloader, cache, stats);
Dispatcher是干什么的呢?这是一个分发器,所有的请求都在这里分发。
最后new Picasso对象返回。
--------------------------------with()到底结束--------------------
public RequestCreator load(Uri uri) { return new RequestCreator(this, uri, 0); }
RequestCreator 是用来创建一个图片下载请求的类
--------------------------into()-------------------------------------
public void into(ImageView target, Callback callback) { long started = System.nanoTime(); checkMain(); if (target == null) { throw new IllegalArgumentException("Target must not be null."); } if (!data.hasImage()) { picasso.cancelRequest(target); if (setPlaceholder) { setPlaceholder(target, getPlaceholderDrawable()); } return; } if (deferred) { if (data.hasSize()) { throw new IllegalStateException("Fit cannot be used with resize."); } int width = target.getWidth(); int height = target.getHeight(); if (width == 0 || height == 0) { if (setPlaceholder) { setPlaceholder(target, getPlaceholderDrawable()); } picasso.defer(target, new DeferredRequestCreator(this, target, callback)); return; } data.resize(width, height); } Request request = createRequest(started); String requestKey = createKey(request); if (shouldReadFromMemoryCache(memoryPolicy)) { Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey); if (bitmap != null) { picasso.cancelRequest(target); setBitmap(target, picasso.context, bitmap, MEMORY, noFade, picasso.indicatorsEnabled); if (picasso.loggingEnabled) { log(OWNER_MAIN, VERB_COMPLETED, request.plainId(), "from " + MEMORY); } if (callback != null) { callback.onSuccess(); } return; } } if (setPlaceholder) { setPlaceholder(target, getPlaceholderDrawable()); } Action action = new ImageViewAction(picasso, target, request, memoryPolicy, networkPolicy, errorResId, errorDrawable, requestKey, tag, callback, noFade); picasso.enqueueAndSubmit(action); }
首先记录下开始时间,然后检查是不是主线程执行的。
if (!data.hasImage())是什么意思呢?data是this.data = new Request.Builder(uri, resourceId, picasso.defaultBitmapConfig);
boolean hasImage() { return uri != null || resourceId != 0; }
所以这里是返回true的,所以暂时判断里的内容没有执行
if (deferred) {//deferred在这里是默认值false,所以花括号里的内容也没有执行
Request request = createRequest(started); //这里创建了请求,给请求唯一的id,url,并且可以转换request String requestKey = createKey(request); //给请求创建了一个key
if (shouldReadFromMemoryCache(memoryPolicy)) { 这里默认是进去的 Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey); 先根据requestKey到cache里找 如果cache里能找到,就取消请求,直接设置 if (callback != null) { callback.onSuccess(); } //如果我们之前传callback进来的话,在成功设置图片后,还可以回调这个方法 如果cache里没有找到的话,
if (setPlaceholder) {
setPlaceholder(target, getPlaceholderDrawable());
}//看有没有设置一个加载时默认显示的图片
最重要的一行
Action action = new ImageViewAction(picasso, target, request, memoryPolicy, networkPolicy, errorResId, errorDrawable, requestKey, tag, callback, noFade);
Action代表了一个具体的加载任务,里面有complete和error方法,主要用于回调
U最后
picasso.enqueueAndSubmit(action);
void enqueueAndSubmit(Action action) { Object target = action.getTarget(); //这个target就是ImageView if (target != null && targetToAction.get(target) != action) { //如果这个image之前还没有请求过 // This will also check we are on the main thread. cancelExistingRequest(target); targetToAction.put(target, action); } submit(action); }
if里的,如果请求已经存在,则取消请求。重新放进去一遍
最后提交
void submit(Action action) { dispatcher.dispatchSubmit(action); }
void dispatchSubmit(Action action) { handler.sendMessage(handler.obtainMessage(REQUEST_SUBMIT, action)); }
这时候这个Dispatcher就起到分发的作用。
Dispatcher里的handleMessage方法里的
case REQUEST_SUBMIT: { Action action = (Action) msg.obj; dispatcher.performSubmit(action); break; }
void performSubmit(Action action) { performSubmit(action, true); } void performSubmit(Action action, boolean dismissFailed) { if (pausedTags.contains(action.getTag())) { pausedActions.put(action.getTarget(), action); if (action.getPicasso().loggingEnabled) { log(OWNER_DISPATCHER, VERB_PAUSED, action.request.logId(), "because tag ‘" + action.getTag() + "‘ is paused"); } return; } BitmapHunter hunter = hunterMap.get(action.getKey()); if (hunter != null) { hunter.attach(action); return; } if (service.isShutdown()) { if (action.getPicasso().loggingEnabled) { log(OWNER_DISPATCHER, VERB_IGNORED, action.request.logId(), "because shut down"); } return; } hunter = forRequest(action.getPicasso(), this, cache, stats, action); hunter.future = service.submit(hunter); hunterMap.put(action.getKey(), hunter); if (dismissFailed) { failedActions.remove(action.getTarget()); } if (action.getPicasso().loggingEnabled) { log(OWNER_DISPATCHER, VERB_ENQUEUED, action.request.logId()); } }
注意这里的,hunter是一个Runnable,负责具体的加载,把最后加载的结果通过dispatcher分发出去
if (result == null) { dispatcher.dispatchFailed(this); } else { dispatcher.dispatchComplete(this); }
这个是run方法里的一小段代码
标签:
原文地址:http://my.oschina.net/u/1777377/blog/413110