Picasso源码完全解析(二)--Picasso实例的创建
Picasso源码完全解析(三)--Request和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的滑动状态来暂停和恢复请求。