美文网首页
Picasso流程

Picasso流程

作者: 一串钥匙链 | 来源:发表于2019-03-23 21:30 被阅读0次

    Picasso

    Picasso的入口是get方法,是个dcl + volatile 的单例

    static volatile Picasso singleton = null;
      public static Picasso get() {
        if (singleton == null) {
          synchronized (Picasso.class) {
            if (singleton == null) {
              if (PicassoProvider.context == null) {
                throw new IllegalStateException("context == null");
              }
              singleton = new Builder(PicassoProvider.context).build();
            }
          }
        }
        return singleton;
      }
    

    PicassoProvider 是个ContentProvider 仅为了拿到context

    
    @RestrictTo(LIBRARY)
    public final class PicassoProvider extends ContentProvider {
    
      @SuppressLint("StaticFieldLeak") static Context context;
    
      @Override public boolean onCreate() {
        context = getContext();
        return true;
      }
    
      @Nullable @Override
      public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
          @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        return null;
      }
    
      @Nullable @Override public String getType(@NonNull Uri uri) {
        return null;
      }
    
      @Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        return null;
      }
    
      @Override public int delete(@NonNull Uri uri, @Nullable String selection,
          @Nullable String[] selectionArgs) {
        return 0;
      }
    
      @Override
      public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
          @Nullable String[] selectionArgs) {
        return 0;
      }
    }
    

    Builder

    public static class Builder {
        private final Context context;
        private Downloader downloader;
        private ExecutorService service;
        private Cache cache;
        private Listener listener;
        private RequestTransformer transformer;
        private List<RequestHandler> requestHandlers;
        private Bitmap.Config defaultBitmapConfig;
    
        private boolean indicatorsEnabled;
        private boolean loggingEnabled;
    
        /** Start building a new {@link Picasso} instance. */
        public Builder(@NonNull Context context) {
          if (context == null) {
            throw new IllegalArgumentException("Context must not be null.");
          }
          //用的是ApplicationContext
          this.context = context.getApplicationContext();
        }
    /** Create the {@link Picasso} instance. */
        public Picasso build() {
          Context context = this.context;
    
    //下载器 默认下载文件夹是应用的缓存文件夹下的picasso-cache  5 - 50m的空间 ,实际缓存使用的是OkHttpClient的缓存功能
          if (downloader == null) {
            downloader = new OkHttp3Downloader(context);
          }
          //内存缓存 内部持有一个android.util.LruCache 缓存的值是BitmapAndSize 就是bitmap 和 的字节数
          if (cache == null) {
            cache = new LruCache(context);
          }
          //线程池 有3个核心线程 一个优先级无界阻塞队列 线程工厂 设置了线程优先级为10 THREAD_PRIORITY_BACKGROUND
          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);
    //初始化Picasso
          return new Picasso(context, dispatcher, cache, listener, transformer, requestHandlers, stats,
              defaultBitmapConfig, indicatorsEnabled, loggingEnabled);
        }
      }
    

    Picasso的构造方法

    Picasso(Context context, Dispatcher dispatcher, Cache cache, Listener listener,
          RequestTransformer requestTransformer, List<RequestHandler> extraRequestHandlers, Stats stats,
          Bitmap.Config defaultBitmapConfig, boolean indicatorsEnabled, boolean loggingEnabled) {
        this.context = context;
        this.dispatcher = dispatcher;
        this.cache = cache;
        this.listener = listener;
        this.requestTransformer = requestTransformer;
        this.defaultBitmapConfig = defaultBitmapConfig;
    
        int builtInHandlers = 7; // Adjust this as internal handlers are added or removed.
        int extraCount = (extraRequestHandlers != null ? extraRequestHandlers.size() : 0);
        List<RequestHandler> allRequestHandlers = new ArrayList<>(builtInHandlers + extraCount);
    
    //添加RRequestHandler  RequestHandler 主要是判断能否处理请求,处理请求
        // ResourceRequestHandler needs to be the first in the list to avoid
        // forcing other RequestHandlers to perform null checks on request.uri
        // to cover the (request.resourceId != 0) case.
        //先添加资源处理器 
        allRequestHandlers.add(new ResourceRequestHandler(context));
        if (extraRequestHandlers != null) {
          allRequestHandlers.addAll(extraRequestHandlers);
        }
        //添加联系人照片处理器
        allRequestHandlers.add(new ContactsPhotoRequestHandler(context));
        //添加照片处理器
        allRequestHandlers.add(new MediaStoreRequestHandler(context));
        //content协议
        allRequestHandlers.add(new ContentStreamRequestHandler(context));
        //asset
        allRequestHandlers.add(new AssetRequestHandler(context));
        //file
        allRequestHandlers.add(new FileRequestHandler(context));
        //网络
        allRequestHandlers.add(new NetworkRequestHandler(dispatcher.downloader, stats));
        requestHandlers = Collections.unmodifiableList(allRequestHandlers);
    
        this.stats = stats;
        this.targetToAction = new WeakHashMap<>();
        this.targetToDeferredRequestCreator = new WeakHashMap<>();
        this.indicatorsEnabled = indicatorsEnabled;
        this.loggingEnabled = loggingEnabled;
        this.referenceQueue = new ReferenceQueue<>();
        this.cleanupThread = new CleanupThread(referenceQueue, HANDLER);
        this.cleanupThread.start();
      }
    

    load 方法最后会返回RequestCreator

      public RequestCreator load(@Nullable Uri uri) {
        return new RequestCreator(this, uri, 0);
      }
    

    RequestCreator 中有一些常用方法

    设置占位图

      public RequestCreator placeholder(@DrawableRes int placeholderResId) {
        if (!setPlaceholder) {
          throw new IllegalStateException("Already explicitly declared as no placeholder.");
        }
        if (placeholderResId == 0) {
          throw new IllegalArgumentException("Placeholder image resource invalid.");
        }
        if (placeholderDrawable != null) {
          throw new IllegalStateException("Placeholder image already set.");
        }
        this.placeholderResId = placeholderResId;
        return this;
      }
    
    

    设置出错之后的图片

      public RequestCreator error(@DrawableRes int errorResId) {
        if (errorResId == 0) {
          throw new IllegalArgumentException("Error image resource invalid.");
        }
        if (errorDrawable != null) {
          throw new IllegalStateException("Error image already set.");
        }
        this.errorResId = errorResId;
        return this;
      }
    

    设置tag

    public RequestCreator tag(@NonNull Object tag) {
        if (tag == null) {
          throw new IllegalArgumentException("Tag invalid.");
        }
        if (this.tag != null) {
          throw new IllegalStateException("Tag already set.");
        }
        this.tag = tag;
        return this;
      }
    
    /** Resize the image to the specified size in pixels. */
      public RequestCreator resize(int targetWidth, int targetHeight) {
          //data是Request.Builder
        data.resize(targetWidth, targetHeight);
        return this;
      }
    
      public RequestCreator centerCrop() {
        data.centerCrop(Gravity.CENTER);
        return this;
      }
    
       public RequestCreator centerInside() {
        data.centerInside();
        return this;
      }
    
        public RequestCreator transform(@NonNull Transformation transformation) {
        data.transform(transformation);
        return this;
      }
    
        public RequestCreator transform(@NonNull List<? extends Transformation> transformations) {
        data.transform(transformations);
        return this;
      }
    
       public RequestCreator networkPolicy(@NonNull NetworkPolicy policy,
          @NonNull NetworkPolicy... additional) {
        if (policy == null) {
          throw new IllegalArgumentException("Network policy cannot be null.");
        }
        this.networkPolicy |= policy.index;
        if (additional == null) {
          throw new IllegalArgumentException("Network policy cannot be null.");
        }
        if (additional.length > 0) {
          for (NetworkPolicy networkPolicy : additional) {
            if (networkPolicy == null) {
              throw new IllegalArgumentException("Network policy cannot be null.");
            }
            this.networkPolicy |= networkPolicy.index;
          }
        }
        return this;
      }
    
      //等等中间方法
    

    终结方法

    get

    
       public Bitmap get() throws IOException {
        long started = System.nanoTime();
        checkNotMain();
    
        if (deferred) {
          throw new IllegalStateException("Fit cannot be used with get.");
        }
        if (!data.hasImage()) {
          return null;
        }
    
    //创建request
        Request finalData = createRequest(started);
        String key = createKey(finalData, new StringBuilder());
    //创建action Action是一个请求动作 持有 请求 key 策略等
        Action action = new GetAction(picasso, finalData, memoryPolicy, networkPolicy, tag, key);
        //获取到BitmapHunter
        return forRequest(picasso, picasso.dispatcher, picasso.cache, picasso.stats, action).hunt();
      }
    

    into方法

      public void into(ImageView target, Callback callback) {
        long started = System.nanoTime();
        //into要在主线程调用
        checkMain();
    
        if (target == null) {
          throw new IllegalArgumentException("Target must not be null.");
        }
    
    //uri 和 资源有一个有即可
        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 和key
        Request request = createRequest(started);
        String requestKey = createKey(request);
    
    //是否从内存缓存读取 默认是true
        if (shouldReadFromMemoryCache(memoryPolicy)) {
            //picasso从Lrucache中获取
          Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey);
          if (bitmap != null) {
              //如果获取到 取消请求
            picasso.cancelRequest(target);
            //设置bitmap
            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);
      }
    
      void enqueueAndSubmit(Action action) {
        Object target = action.getTarget();
        if (target != null && targetToAction.get(target) != action) {
          // This will also check we are on the main thread.
          //如果已经存在这个请求动作先取消以前的再缓存最新的
          cancelExistingRequest(target);
          targetToAction.put(target, action);
        }
        submit(action);
      }
    
    
      void cancelExistingRequest(Object target) {
        checkMain();
        //删除缓存
        Action action = targetToAction.remove(target);
        if (action != null) {
          action.cancel();
          dispatcher.dispatchCancel(action);//performCancel
        }
        if (target instanceof ImageView) {
          ImageView targetImageView = (ImageView) target;
          DeferredRequestCreator deferredRequestCreator =
              targetToDeferredRequestCreator.remove(targetImageView);
          if (deferredRequestCreator != null) {
            deferredRequestCreator.cancel();
          }
        }
      }
    
      void performCancel(Action action) {
        String key = action.getKey();
        BitmapHunter hunter = hunterMap.get(key);
        if (hunter != null) {
          hunter.detach(action);
          if (hunter.cancel()) {
            hunterMap.remove(key);
            if (action.getPicasso().loggingEnabled) {
              log(OWNER_DISPATCHER, VERB_CANCELED, action.getRequest().logId());
            }
          }
        }
    
        if (pausedTags.contains(action.getTag())) {
          pausedActions.remove(action.getTarget());
          if (action.getPicasso().loggingEnabled) {
            log(OWNER_DISPATCHER, VERB_CANCELED, action.getRequest().logId(),
                "because paused request got canceled");
          }
        }
    
        Action remove = failedActions.remove(action.getTarget());
        if (remove != null && remove.getPicasso().loggingEnabled) {
          log(OWNER_DISPATCHER, VERB_CANCELED, remove.getRequest().logId(), "from replaying");
        }
      }
    

    submit

     void submit(Action action) {
        dispatcher.dispatchSubmit(action);
      }
    
      
      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());
        }
      }
    

    forresult

      static BitmapHunter forRequest(Picasso picasso, Dispatcher dispatcher, Cache cache, Stats stats,
          Action action) {
        Request request = action.getRequest();
        List<RequestHandler> requestHandlers = picasso.getRequestHandlers();
    
        // Index-based loop to avoid allocating an iterator.
        //noinspection ForLoopReplaceableByForEach
        for (int i = 0, count = requestHandlers.size(); i < count; i++) {
            //获取到一个能够处理这个请求的RequestHandler 构造一个BitmapHunter
          RequestHandler requestHandler = requestHandlers.get(i);
          if (requestHandler.canHandleRequest(request)) {
            return new BitmapHunter(picasso, dispatcher, cache, stats, action, requestHandler);
          }
        }
    
        return new BitmapHunter(picasso, dispatcher, cache, stats, action, ERRORING_HANDLER);
      }
    

    PicassoExecutorService.submit

     public Future<?> submit(Runnable task) {
        PicassoFutureTask ftask = new PicassoFutureTask((BitmapHunter) task);
        execute(ftask);
        return ftask;
      }
    
      @Override public void run() {
        try {
          updateThreadName(data);
    
          if (picasso.loggingEnabled) {
            log(OWNER_HUNTER, VERB_EXECUTING, getLogIdsForHunter(this));
          }
    
          result = hunt();
    
          if (result == null) {
            dispatcher.dispatchFailed(this);
          } else {
            dispatcher.dispatchComplete(this);
          }
        } catch (NetworkRequestHandler.ResponseException e) {
          if (!NetworkPolicy.isOfflineOnly(e.networkPolicy) || e.code != 504) {
            exception = e;
          }
          dispatcher.dispatchFailed(this);
        } catch (IOException e) {
          exception = e;
          dispatcher.dispatchRetry(this);
        } catch (OutOfMemoryError e) {
          StringWriter writer = new StringWriter();
          stats.createSnapshot().dump(new PrintWriter(writer));
          exception = new RuntimeException(writer.toString(), e);
          dispatcher.dispatchFailed(this);
        } catch (Exception e) {
          exception = e;
          dispatcher.dispatchFailed(this);
        } finally {
          Thread.currentThread().setName(Utils.THREAD_IDLE_NAME);
        }
      }
    
      Bitmap hunt() throws IOException {
        Bitmap bitmap = null;
    
    //可以从内存缓存中读取
        if (shouldReadFromMemoryCache(memoryPolicy)) {
            //缓存命中
          bitmap = cache.get(key);
          if (bitmap != null) {
            stats.dispatchCacheHit();
            loadedFrom = MEMORY;
            if (picasso.loggingEnabled) {
              log(OWNER_HUNTER, VERB_DECODED, data.logId(), "from cache");
            }
            return bitmap;
          }
        }
    
        networkPolicy = retryCount == 0 ? NetworkPolicy.OFFLINE.index : networkPolicy;
        //RequestHandler 去处理,网络默认是okhttp下载器 拿到从硬盘或者 网络加载
        RequestHandler.Result result = requestHandler.load(data, networkPolicy);
        if (result != null) {
          loadedFrom = result.getLoadedFrom();
          exifOrientation = result.getExifOrientation();
          bitmap = result.getBitmap();
    
          // If there was no Bitmap then we need to decode it from the stream.
          if (bitmap == null) {
            Source source = result.getSource();
            try {
              bitmap = decodeStream(source, data);//大致可认为是BitmapFactory.decodeStream
            } finally {
              try {
                //noinspection ConstantConditions If bitmap is null then source is guranteed non-null.
                source.close();
              } catch (IOException ignored) {
              }
            }
          }
        }
    
        if (bitmap != null) {
          if (picasso.loggingEnabled) {
            log(OWNER_HUNTER, VERB_DECODED, data.logId());
          }
          stats.dispatchBitmapDecoded(bitmap);
          if (data.needsTransformation() || exifOrientation != 0) {
            synchronized (DECODE_LOCK) {
              if (data.needsMatrixTransform() || exifOrientation != 0) {
                bitmap = transformResult(data, bitmap, exifOrientation);
                if (picasso.loggingEnabled) {
                  log(OWNER_HUNTER, VERB_TRANSFORMED, data.logId());
                }
              }
              if (data.hasCustomTransformations()) {
                bitmap = applyCustomTransformations(data.transformations, bitmap);
                if (picasso.loggingEnabled) {
                  log(OWNER_HUNTER, VERB_TRANSFORMED, data.logId(), "from custom transformations");
                }
              }
            }
            if (bitmap != null) {
              stats.dispatchBitmapTransformed(bitmap);
            }
          }
        }
    
        //进行一系列变换之后返回
    
        return bitmap;
      }
    
      void performComplete(BitmapHunter hunter) {
          //先写入缓存
        if (shouldWriteToMemoryCache(hunter.getMemoryPolicy())) {
          cache.set(hunter.getKey(), hunter.getResult());
        }
        //移除需要去处理的key
        hunterMap.remove(hunter.getKey());
        batch(hunter);
        if (hunter.getPicasso().loggingEnabled) {
          log(OWNER_DISPATCHER, VERB_BATCHED, getLogIdsForHunter(hunter), "for completion");
        }
      }
    
        private void batch(BitmapHunter hunter) {
        if (hunter.isCancelled()) {
          return;
        }
        if (hunter.result != null) {
          hunter.result.prepareToDraw();
        }
        batch.add(hunter);
        if (!handler.hasMessages(HUNTER_DELAY_NEXT_BATCH)) {
          handler.sendEmptyMessageDelayed(HUNTER_DELAY_NEXT_BATCH, BATCH_DELAY);
        }
      }
    
        void performBatchComplete() {
        List<BitmapHunter> copy = new ArrayList<>(batch);
        batch.clear();
        mainThreadHandler.sendMessage(mainThreadHandler.obtainMessage(HUNTER_BATCH_COMPLETE, copy));
        logBatch(copy);
      }
    
    case HUNTER_BATCH_COMPLETE: {
              @SuppressWarnings("unchecked") List<BitmapHunter> batch = (List<BitmapHunter>) msg.obj;
              //noinspection ForLoopReplaceableByForEach
              for (int i = 0, n = batch.size(); i < n; i++) {
                BitmapHunter hunter = batch.get(i);
                hunter.picasso.complete(hunter);
              }
              break;
            }
    
      void complete(BitmapHunter hunter) {
        Action single = hunter.getAction();
        List<Action> joined = hunter.getActions();
    
        boolean hasMultiple = joined != null && !joined.isEmpty();
        boolean shouldDeliver = single != null || hasMultiple;
    
        if (!shouldDeliver) {
          return;
        }
    
        Uri uri = hunter.getData().uri;
        Exception exception = hunter.getException();
        Bitmap result = hunter.getResult();
        LoadedFrom from = hunter.getLoadedFrom();
    
        if (single != null) {
          deliverAction(result, from, single, exception);
        }
    
        if (hasMultiple) {
          //noinspection ForLoopReplaceableByForEach
          for (int i = 0, n = joined.size(); i < n; i++) {
            Action join = joined.get(i);
            deliverAction(result, from, join, exception);
          }
        }
    
        if (listener != null && exception != null) {
          listener.onImageLoadFailed(this, uri, exception);
        }
      }
    
      private void deliverAction(Bitmap result, LoadedFrom from, Action action, Exception e) {
        if (action.isCancelled()) {
          return;
        }
        if (!action.willReplay()) {
          targetToAction.remove(action.getTarget());
        }
        if (result != null) {
          if (from == null) {
            throw new AssertionError("LoadedFrom cannot be null.");
          }
          action.complete(result, from);
          if (loggingEnabled) {
            log(OWNER_MAIN, VERB_COMPLETED, action.request.logId(), "from " + from);
          }
        } else {
          action.error(e);
          if (loggingEnabled) {
            log(OWNER_MAIN, VERB_ERRORED, action.request.logId(), e.getMessage());
          }
        }
      }
    
        @Override public void complete(Bitmap result, Picasso.LoadedFrom from) {
        if (result == null) {
          throw new AssertionError(
              String.format("Attempted to complete action with no result!\n%s", this));
        }
    
        ImageView target = this.target.get();
        if (target == null) {
          return;
        }
    
        Context context = picasso.context;
        boolean indicatorsEnabled = picasso.indicatorsEnabled;
        PicassoDrawable.setBitmap(target, context, result, from, noFade, indicatorsEnabled);
    
        if (callback != null) {
          callback.onSuccess();
        }
      }
    
        static void setBitmap(ImageView target, Context context, Bitmap bitmap,
          Picasso.LoadedFrom loadedFrom, boolean noFade, boolean debugging) {
        Drawable placeholder = target.getDrawable();
        if (placeholder instanceof Animatable) {
          ((Animatable) placeholder).stop();
        }
        PicassoDrawable drawable =
            new PicassoDrawable(context, bitmap, placeholder, loadedFrom, noFade, debugging);
        target.setImageDrawable(drawable);
      }
    

    至此流程结束

    大致就是 Picasso 是个单例 load时候 会 创建一个 RequestCreator ,设置一系列属性之后 创建一个Result 和一个 请求动作Action 以ImageView为例 是 ImageViewAction,根据Action 和 能够处理它的RequestHandler生成一个BitmapHunter 它是Runable 之后把他提交到线程池执行 run 方法中主要是hun拿到一个bitmap ,先从缓存中拿 不过没有命中 再从RequestHandler拿,如果是网络的,其实就是通过下载器去下载内部用的是okhttp,okhttp从网络或者磁盘拿 用source 和 从哪里拿的构建一个Result,然后去解码拿到一个Bitmap ,网络的话source 可以拿到inputstream ,大致可认为就是bitmapFactory.decodeSteam这样,拿到之后调用分发器分发结果,分布器中先写入内存缓存,并把BitmapHunter发送到主线程的Hanlder在主线程中调用了action的完成在ImageViewAction的完成方法中构建了一个PicassoDrawable把他设置到ImageView,流程结束

    相关文章

      网友评论

          本文标题:Picasso流程

          本文链接:https://www.haomeiwen.com/subject/zzjevqtx.html