/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.volley;
import android.os.Handler;
import java.util.concurrent.Executor;
/**
* Delivers responses and errors.
*/
/*
* ExecutorDelivery 实现了 ResponseDelivery 接口
*
* 主要功能就是:
* 1.传递 请求、请求结果 or 相应错误 以及 可能有自定义的 Runnable 执行回调操作。
* 2.定义了一个 Executor,因为可能会有自定义的 Runnable 执行回调操作,所以需要它的存在。
* 3.因为有 Executor 和 Runnable 的存在,但是都在子线程内。所以,还
* 需要传入一个 UI 线程的 Handler(大多情况回调都是跟 UI 线程通信)
* 可以在 RequestQueue 类中 搜搜 "new Handler(Looper.getMainLooper())" 关键句
*
* 构造方法也是有趣设计:
*
* 1. Handler 作为参数的构造方法。全 Volley 只有 RequestQueue 内使用,并且传入一个 UI 线程的 Handler
* 可以简单得出:这个构造方法可以指定( 不只是 UI 线程 )线程的 Handler 去处理这个 Runnable
* 看过 Handler 源码的都知道:你给我一个 Runnable,我会 拿到这个 Handler 实例化时的 Looper,再拿到
* MessageQueue 去添加一条 Message ,Runnable 则作为 这个 Message.callback 保存在这,然后在
* Handler.dispatchMessage(...) 的时候,会执行 Message.callback.run()
*
* 所以,这里(不只是 UI 线程)线程的 Handler,说明了可以给其他线程传递( 通信 )。
*
* 2. Executor 作为参数的构造方法。这里由于 Executor 作为外部提供的参数,那么 Handler 也在外面提供了,更具有
* 可定制性。Handler 作为参数的构造方法 就是 这个 Executor 作为参数的构造方法 的升级版。
*
* 因为,ExecutorDelivery 需要 Executor 和 Handler。
* Handler 作为参数的构造方法:实例化了 Executor,Handler由外部提供,这里 Executor 是默认执行
* handler.post(Runnable command)
* Executor 作为参数的构造方法:都需要外部提供。
*
*/
public class ExecutorDelivery implements ResponseDelivery {
/** Used for posting responses, typically to the main thread. */
// 用于处理 Runnable
private final Executor mResponsePoster;
/**
* Creates a new response delivery interface.
*
* @param handler {@link Handler} to post responses on
*/
// Handler 作为参数的构造方法
public ExecutorDelivery(final Handler handler) {
// Make an Executor that just wraps the handler.
/*
* 实例化 Executor,并用 handler 去执行
* execute(Runnable command) 传入的 Runnable
*/
mResponsePoster = new Executor() {
@Override public void execute(Runnable command) {
handler.post(command);
}
};
}
/**
* Creates a new response delivery interface, mockable version
* for testing.
*
* @param executor For running delivery tasks
*/
// Executor 作为参数的构造方法
public ExecutorDelivery(Executor executor) {
mResponsePoster = executor;
}
/*
* Runnable 设置为 null
* 执行 postResponse(Request<?> request, Response<?> response, Runnable runnable)
*/
@Override public void postResponse(Request<?> request, Response<?> response) {
postResponse(request, response, null);
}
@Override
public void postResponse(Request<?> request, Response<?> response, Runnable runnable) {
/*
* 在 Request 做一个标记,标记这个 Request 具有 response
* 可以传递 response 内容,而不是下面的 VolleyError
*/
request.markDelivered();
/*
* 添加tag,用于 debug 调试
* key:post-response
* value:当前线程的 id
*/
request.addMarker("post-response");
// 调用 Executor 去执行回调操作一个 new ResponseDeliveryRunnable
mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));
}
@Override public void postError(Request<?> request, VolleyError error) {
/*
* 添加tag,用于 debug 调试
* key:post-error
* value:当前线程的 id
*/
request.addMarker("post-error");
// Response.error 静态方法,构造一个 Error response
Response<?> response = Response.error(error);
// 调用 Executor 去执行回调操作一个 new ResponseDeliveryRunnable
mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, null));
}
/**
* A Runnable used for delivering network responses to a listener on the
* main thread.
*/
/*
* @formatter:off
*
* ResponseDeliveryRunnable 实现了 Runnable 接口
* 扩展了 run() 的功能:使 run() 过程中 调用了一些 Request 的方法
*/
@SuppressWarnings("rawtypes")
private class ResponseDeliveryRunnable implements Runnable { // @formatter:on
private final Request mRequest;
private final Response mResponse;
private final Runnable mRunnable;
/**
* 构造方法
*
* @param request 请求
* @param response 请求结果
* @param runnable 回调执行线程
*/
public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) {
mRequest = request;
mResponse = response;
mRunnable = runnable;
}
@SuppressWarnings("unchecked") @Override public void run() {
// If this request has canceled, finish it and don't deliver.
/*
* 判断 Request 是否被取消
* 如果取消,调用 finish(),并且返回。即不执行传递
* 如果没取消,继续执行
*/
if (mRequest.isCanceled()) {
mRequest.finish("canceled-at-delivery");
return;
}
// Deliver a normal response or error, depending.
// 判断请求是否成功,选择传递 正常响应 或者 错误
if (mResponse.isSuccess()) {
// 传递 正常响应
mRequest.deliverResponse(mResponse.result);
} else {
// 传递 错误
mRequest.deliverError(mResponse.error);
}
// If this is an intermediate response, add a marker, otherwise we're done
// and the request can be finished.
/*
* Request.intermediate=true 只会在 CacheDispatcher.run() 需要 刷新的情况下 触发
* 可以知道 如果是用的是 缓存 Request,以及缓存 Request 解析出的 Response
*
* // Mark the response as intermediate.
* response.intermediate = true;
*
* // Post the intermediate response back to the user and have
* // the delivery then forward the request along to the network.
* mDelivery.postResponse(request, response, new Runnable() {
* @Override
* public void run() {
* try {
* mNetworkQueue.put(request);
* } catch (InterruptedException e) {
* // Not much we can do about this.
* }
* }
*});
*
* 由于目前 Volley 全局就 RequestQueue 用一个 ExecutorDelivery
* 由此可以看出 mDelivery = ExecutorDelivery
*
* 在拿到缓存 Request 后,由于调用 ExecutorDelivery 的情景都是在拿到 响应 or 错误后
* ( 如果还取得 响应 or 错误,就不存在传递数据逻辑)
* 注: 这里 之所以 Request.intermediate=true 的可能性,只发生在 缓存请求 需要刷新
* 不然,都有了响应,就不需要再次请求了( 执行 finish("done") ),所以不属于 刷新缓存 的
* 情景都 要 finish("done")
*
* 属于 刷新缓存 的情况,会将请求加入到 NetworkQueue 内。
*
* 所以得出了 如果从缓存中拿出 Request 判断需要刷新的话
*
* 其实:主要为了打印一个 intermediate-response 的 MarkLog
*/
if (mResponse.intermediate) {
/*
* 属于 刷新缓存,这是 tag = "intermediate-response" ,并且会在下面的 Runnable
* 执行 过程中 执行 NetworkQueue.put(request) 操作
*/
mRequest.addMarker("intermediate-response");
} else {
// 不属于 刷新缓存,标记完成。
mRequest.finish("done");
}
// If we have been provided a post-delivery runnable, run it.
// 如果回调执行线程不为 null,则执行
if (mRunnable != null) {
mRunnable.run();
}
}
}
}