Skip to content

Android Picasso

Posted on:August 26, 2021 at 21:08:44 GMT+8

设计

Picasso 加载图片的流程

Picasso.get().load("").into(imageView);

Picasso.get()  创建一个 Picasso 单例,内部使用了建造者模式,单例模式和建造者模式。

load 方法返回一个 RequestCreator。

into 方法中中创建一个 request,request 作为创建 action 的参数之一,再 picasso.enqueueAndSubmit(action);

picasso submit 这个 action。

dispatcher.dispatchSubmit action,dispatcher 中的 handler 发送一个 message:

void dispatchSubmit(Action action) {
  handler.sendMessage(handler.obtainMessage(REQUEST_SUBMIT, action));
}

dispatcher 内部有个 static 的 DispatcherHandler 类。收到 REQUEST_SUBMIT 类型的 message 会,dispatcher.performSubmit 。

尝试从 dispatcher 的 hunterMap 中根据 action 的 key 获取 BitmapHunter,将 hunter attach action。

上一步没获取到 hunter 时,dispatcher forRequest 创建 hunter,创建时将创建 picasso 时设置的 requestHander 设给 hunter:

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 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);
}

再:

hunter.future = service.submit(hunter);

BitmapHunter 实现了 Runnable,run 方法中 hunt 方法,从内存缓存中读,

读不到 requestHandler.load ,返回 RequestHandler.Result,

decodeStream

stats.dispatchBitmapDecoded

hunt 方法执行完返回 Bitmap,

result = hunt();

if (result == null) {
  dispatcher.dispatchFailed(this);
} else {
  dispatcher.dispatchComplete(this);
}
void dispatchComplete(BitmapHunter hunter) {
  handler.sendMessage(handler.obtainMessage(HUNTER_COMPLETE, hunter));
}
case HUNTER_COMPLETE: {
  BitmapHunter hunter = (BitmapHunter) msg.obj;
  dispatcher.performComplete(hunter);
  break;
}

写入内存缓存,再 dispatcher batch(),

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);
  }
}

200 ms 后发送 HUNTER_DELAY_NEXT_BATCH message,

void performBatchComplete() {
  List<BitmapHunter> copy = new ArrayList<>(batch);
  batch.clear();
  mainThreadHandler.sendMessage(mainThreadHandler.obtainMessage(HUNTER_BATCH_COMPLETE, copy));
  logBatch(copy);
}

mainThreadHandler 是 picasso 中的 HANDLER,

complete
action.complete(result, from);

ImageViewAction

@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();
  }
}
/**
 * Create or update the drawable on the target {@link ImageView} to display the supplied bitmap
 * image.
 */
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);
}