picasso的源码分析(一)

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

转载于:https://my.oschina.net/u/1777377/blog/413110

毕加索制版系统,支持单面,绞花,提花,嵌花等复杂花型制作。 Picasso横机花样制版系统使用说明      绍兴越发机械有限公司  - 1 -  目录   1.简介……………………………………………………………………………………………….2 2.软件运行要求……………………………………………………………………………….……2 3.界面风格……………………………………………………………….…………………………2 4.主要功能……………………………………………………….…………………………………2  4.1 设计绘图……………………………………………………….…………………………2  4.2 文件操作……………………………………………………….…………………………3  4.3 文件类别……………………………………………………….…………………………3  4.4 程序自动生成……………………………………………………….……………………3  4.5 程序资料编辑……………………………………………………….……………………3 5.菜单和工具栏的说明………………………………………………………………………….…4  5.1 工具栏图标……………………………………………………...…………………..……4  5.2 第一作图区编织针法[P1]…………………………………….……………….………9 6.快捷键…………………………………………………………………...………………………10 7.第二作图区、指示窗的说明……………………………………………………………………11  7.1 功能线表……………………………………………………………...…………………11  7.2 部分功能线操作指南…………………………………………………...………………15  7.3 编织型式代码…………………………………………………………...………………18 8.初学者使用……………………
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值