Picasso源码完全解析(六)--请求的取消、暂停、和恢复

来源:互联网 发布:2016开淘宝店晚不晚 编辑:程序博客网 时间:2024/05/01 21:41


Picasso源码完全解析(一)--概述

Picasso源码完全解析(二)--Picasso实例的创建

Picasso源码完全解析(三)--Request和Action的创建

Picasso源码完全解析(四)--Action分发和执行

Picasso源码完全解析(五)--图片的获取(BitmapHunter)

Picasso源码完全解析(六)--请求的取消、暂停、和恢复

Picasso源码完全解析(七)-- CleanupThread 取消请求


Picasso源码完全解析(六)--请求的取消、暂停、和恢复


Picasso为管理请求,提供了取消、暂停和恢复请求的方法。

请求的取消

请求的取消通常是通过picasso.cancel方法执行的,最终会调用这个方法:

    private void cancelExistingRequest(Object target) {    checkMain();    Action action = targetToAction.remove(target);    if (action != null) {        action.cancel();        dispatcher.dispatchCancel(action);    }    if (target instanceof ImageView) {        ImageView targetImageView = (ImageView) target;        DeferredRequestCreator deferredRequestCreator = targetToDeferredRequestCreator.remove(targetImageView);        if (deferredRequestCreator != null) {            deferredRequestCreator.cancel();        }    }}

可以看到 是通过dispatcher.dispatchCancel(action)来执行的。在之前的基础上我们很容易明白,这是通过Dispatcher进行分发处理的。

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

没错,最终是通过

hunter.cancel()

来暂停请求的。

boolean cancel() {    return action == null            && (actions == null || actions.isEmpty())            && future != null            && future.cancel(false);}

最终的取消是通过 future.cancel()完成的。

请求的暂停

请求的暂停是通过 picasso.pause()来完成的,具体调用流程和cancel类似,这里不再赘述,通过分析,发现最终还是通过

 hunter.cancel()

来暂停请求的,也就是暂停请求只不过是临时取消了这个请求。

请求的恢复

有请求的暂停也就有请求的恢复,请求的恢复是通过picass.resume()调用完成的,也是通过Dispatcher进行分的,

void performResumeTag(Object tag) {    // Trying to resume a tag that is not paused.    if (!pausedTags.remove(tag)) {        return;    }    List<Action> batch = null;    for (Iterator<Action> i = pausedActions.values().iterator(); i.hasNext(); ) {        Action action = i.next();        if (action.getTag().equals(tag)) {            if (batch == null) {                batch = new ArrayList<>();            }            batch.add(action);            i.remove();        }    }    if (batch != null) {        mainThreadHandler.sendMessage(mainThreadHandler.obtainMessage(REQUEST_BATCH_RESUME, batch));    }}

可以看到这里是通过mainThreadHandler发送消息,我们知道mainThreadHandler是Picasso实例所在线程也就是Main线程的Handler,看看消息是如何处理的:

   case REQUEST_BATCH_RESUME:                @SuppressWarnings("unchecked") List<Action> batch = (List<Action>) msg.obj;                //noinspection ForLoopReplaceableByForEach                for (int i = 0, n = batch.size(); i < n; i++) {                    Action action = batch.get(i);                    action.picasso.resumeAction(action);                }                break;

再看看 action.picasso.resumeAction(action);

 void resumeAction(Action action) {    Bitmap bitmap = null;    if (shouldReadFromMemoryCache(action.memoryPolicy)) {        bitmap = quickMemoryCacheCheck(action.getKey());    }    if (bitmap != null) {        // Resumed action is cached, complete immediately.        deliverAction(bitmap, MEMORY, action, null);        if (loggingEnabled) {            log(OWNER_MAIN, VERB_COMPLETED, action.request.logId(), "from " + MEMORY);        }    } else {        // Re-submit the action to the executor.        enqueueAndSubmit(action);        if (loggingEnabled) {            log(OWNER_MAIN, VERB_RESUMED, action.request.logId());        }    }}

很明显,如果能从内存缓存中取得结果就从内存中去,否在重新提交该action。

通过上面的分析可以看到,picasso暂停和恢复请求,实际上是取消请求然后再重新提交请求,并不是真正意义上的暂停和恢复请求。

我们在实际使用过程中,往往将picasso的tag设置为统一对象,可以是所在activity的context,并在activity的生命周期中做相应的控制,或者在列表中使用的时候,为了滑动的流畅,可以根据list的滑动状态来暂停和恢复请求。