您的位置:首页 > 移动开发 > Android开发

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

2017-05-17 09:14 896 查看


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的滑动状态来暂停和恢复请求。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息