picasso的源码分析(一)

picasso的使用很是简单。咱们只须要一行代码就够java

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对象的建立很是复杂ide

咱们直接看build方法post

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时能够调用他去修改请求)。ui

    接下来是Stats stats = new Stats(cache).this

    能够看下这里类里面的主要的成员变量url

    

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;

    主要为了记录一些缓存的命中次数,下载的文件大小,下载次数,原始文件大小等等信息,暂时先不看是干什么用的spa

    这里有一个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方法里的一小段代码

相关文章
相关标签/搜索