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


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的滑动状态来暂停和恢复请求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值