Picasso框架分析

Picasso框架分析

https://github.com/square/picasso

implementation 'com.squareup.picasso:picasso:2.71828'

先来一张简图

这里写图片描述

核心组成

  • Picasso:外观设计模式、门户
  • Dispatcher:任务的分发调度者(运行在单独的线程中)
  • PicassoExecutorService:线程池
  • BitmapHunter:执行任务(模板设计模式)
  • RequestHandler:任务的具体处理者(抽象类)
  • Request:请求任务的封装
  • Action:动作的封装

工作流程

    Picasso picasso = new Picasso.Builder(getContext()).build();//这里可以使用单例模式包装一下
    picasso.load(uri).into(imageView);
  1. 调用load()
    2.创建一个RequestCreator
  2. 调用into()
  3. 创建一个Request
  4. 创建一个对应的Action
  5. 通过Picasso提交给Dispatcher
  6. 创建BitmapHunter(创建时:查找到具体的处理者)
  7. 通过PicassoExecutorService去执行该BitmapHunter

具体的BitmapHunter执行任务

@Override public void run() {
    try {
      updateThreadName(data);

      if (picasso.loggingEnabled) {
        log(OWNER_HUNTER, VERB_EXECUTING, getLogIdsForHunter(this));
      }

      result = hunt(); // hunt()方法执行具体图片获取逻辑,下面都是异常处理

      if (!result.hasBitmap()) {
        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) {// 捕获了内存溢出的异常
      Buffer buffer = new Buffer();
      try {
        stats.createSnapshot().dump(buffer);
      } catch (IOException ioe) {
        throw new AssertionError(ioe);
      }
      exception = new RuntimeException(buffer.readUtf8(), e);
      dispatcher.dispatchFailed(this);
    } catch (Exception e) {
      exception = e;
      dispatcher.dispatchFailed(this);
    } finally {
      Thread.currentThread().setName(Utils.THREAD_IDLE_NAME);
    }
  }

Result hunt() throws IOException {

//-----------------------------------------------------------------------
// 一、先取内存缓存
    if (shouldReadFromMemoryCache(data.memoryPolicy)) {
      Bitmap bitmap = cache.get(key);
      if (bitmap != null) {
        stats.dispatchCacheHit();
        if (picasso.loggingEnabled) {
          log(OWNER_HUNTER, VERB_DECODED, data.logId(), "from cache");
        }
        return new Result(bitmap, MEMORY);
      }
    }
//-----------------------------------------------------------------------
    if (retryCount == 0) {
      data = data.newBuilder().networkPolicy(NetworkPolicy.OFFLINE).build();
    }

//--------------------------------------------------------------------------------
// 二、通过具体的执行者去获取图片(如果是网络请求,使用的是OkHttp去下载)
    final AtomicReference<Result> resultReference = new AtomicReference<>();
    final AtomicReference<Throwable> exceptionReference = new AtomicReference<>();
    final CountDownLatch latch = new CountDownLatch(1);// 1.线程同步工具
    try {
      requestHandler.load(picasso, data, new RequestHandler.Callback() {
        @Override public void onSuccess(@Nullable Result result) {
          resultReference.set(result);
          latch.countDown();// 3.获取到图片后、结束等待
        }

        @Override public void onError(@NonNull Throwable t) {
          exceptionReference.set(t);
          latch.countDown();
        }
      });

      latch.await();// 2.在此等待
    } catch (InterruptedException ie) {
      InterruptedIOException interruptedIoException = new InterruptedIOException();
      interruptedIoException.initCause(ie);
      throw interruptedIoException;
    }

    Throwable throwable = exceptionReference.get();
    if (throwable != null) {
      if (throwable instanceof IOException) {
        throw (IOException) throwable;
      }
      if (throwable instanceof Error) {
        throw (Error) throwable;
      }
      if (throwable instanceof RuntimeException) {
        throw (RuntimeException) throwable;
      }
      throw new RuntimeException(throwable);
    }

    Result result = resultReference.get();
//--------------------------------------------------------------------------------
    if (result.hasBitmap()) {
      if (picasso.loggingEnabled) {
        log(OWNER_HUNTER, VERB_DECODED, data.logId());
      }
      Bitmap bitmap = result.getBitmap();
      stats.dispatchBitmapDecoded(bitmap);
    // 三、图片处理
      int exifOrientation = result.getExifRotation();
      if (data.needsTransformation() || exifOrientation != 0) {
        if (data.needsMatrixTransform() || exifOrientation != 0) {
          bitmap = transformResult(data, bitmap, exifOrientation);
          if (picasso.loggingEnabled) {
            log(OWNER_HUNTER, VERB_TRANSFORMED, data.logId());
          }
        }

        result = new Result(bitmap, result.getLoadedFrom(), exifOrientation);
        if (data.hasCustomTransformations()) {
          result = applyCustomTransformations(data.transformations, result);
          if (picasso.loggingEnabled) {
            log(OWNER_HUNTER, VERB_TRANSFORMED, data.logId(),
                "from custom transformations");
          }
        }
      }
      if (result.hasBitmap()) {
        stats.dispatchBitmapTransformed(result.getBitmap());
      }
    }

    return result;
  }

上面代码逻很简单、分为三步:(网络加载为例)
1.缓存中取
2.网络加载
3.图片处理


上面好像并没有看到磁盘缓存?
其实Picasso的磁盘缓存是使用了Okhttp的缓存,看代码

NetworkRequestHandler
@Override public void load(@NonNull Picasso picasso, @NonNull final Request request, @NonNull
  final Callback callback) {
    okhttp3.Request callRequest = createRequest(request);
    // 使用Okhttp发起请求
    callFactory.newCall(callRequest).enqueue(new okhttp3.Callback() {
      @Override 
      public void onResponse(Call call, Response response) {
        if (!response.isSuccessful()) {
          callback.onError(new ResponseException(response.code(), request.networkPolicy));
          return;
        }
    // 在此判断是磁盘缓存还是网络获取
        Picasso.LoadedFrom loadedFrom = response.cacheResponse() == null ? NETWORK : DISK;
    ...
      }

      @Override public void onFailure(Call call, IOException e) {
        callback.onError(e);
      }
    });
  }

Picasso是一个轻量级的图片加载框架、代码量很少、使用起来也很方便,但是不支持GIF图片的加载。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值