代码示例从github上获取(不是自己写的 ):https://github.com/jdsjlzx/RetrofitDemo
先看OKHttp的使用,最简单的:
//1.创建OkHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
//2.创建Request对象,设置一个url地址(百度地址),设置请求方式。
Request request = new Request.Builder().url("http://www.baidu.com").method("GET",null).build();
//3.创建一个call对象,参数就是Request请求对象
Call call = okHttpClient.newCall(request);
//4.请求加入调度,重写回调方法
call.enqueue(new Callback() {
//请求失败执行的方法
@Override
public void onFailure(Call call, IOException e) {
}
//请求成功执行的方法
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
主要涉及3个类:
- OkHttpClient
- RealCall
- Request
public OkHttpClient() {
this(new Builder());
}
... ...
public static final class Builder {
Dispatcher dispatcher;
Proxy proxy;
List<Protocol> protocols;
List<ConnectionSpec> connectionSpecs;
final List<Interceptor> interceptors = new ArrayList<>();
final List<Interceptor> networkInterceptors = new ArrayList<>();
ProxySelector proxySelector;
CookieJar cookieJar;
Cache cache;
InternalCache internalCache;
SocketFactory socketFactory;
SSLSocketFactory sslSocketFactory;
TrustRootIndex trustRootIndex;
HostnameVerifier hostnameVerifier;
CertificatePinner certificatePinner;
Authenticator proxyAuthenticator;
Authenticator authenticator;
ConnectionPool connectionPool;
Dns dns;
boolean followSslRedirects;
boolean followRedirects;
boolean retryOnConnectionFailure;
int connectTimeout;
int readTimeout;
int writeTimeout;
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;
connectionSpecs = DEFAULT_CONNECTION_SPECS;
proxySelector = ProxySelector.getDefault();
cookieJar = CookieJar.NO_COOKIES;
socketFactory = SocketFactory.getDefault();
hostnameVerifier = OkHostnameVerifier.INSTANCE;
certificatePinner = CertificatePinner.DEFAULT;
proxyAuthenticator = Authenticator.NONE;
authenticator = Authenticator.NONE;
connectionPool = new ConnectionPool();
dns = Dns.SYSTEM;
followSslRedirects = true;
followRedirects = true;
retryOnConnectionFailure = true;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
}
通过这些代码我们可以知道OkHttpClient中包含了在HTTP网络访问的时候需要的一些参数值,为了使用方便,有些参数值由默认值设置:
socketFactory = SocketFactory.getDefault();
public static SocketFactory getDefault()
{
synchronized (SocketFactory.class) {
if (theFactory == null) {
//
// Different implementations of this method SHOULD
// work rather differently. For example, driving
// this from a system property, or using a different
// implementation than JavaSoft's.
//
theFactory = new DefaultSocketFactory();
}
}
return theFactory;
}
dns = Dns.SYSTEM;
public interface Dns {
/**
* A DNS that uses {@link InetAddress#getAllByName} to ask the underlying operating system to
* lookup IP addresses. Most custom {@link Dns} implementations should delegate to this instance.
*/
Dns SYSTEM = new Dns() {
@Override public List<InetAddress> lookup(String hostname) throws UnknownHostException {
if (hostname == null) throw new UnknownHostException("hostname == null");
return Arrays.asList(InetAddress.getAllByName(hostname));
}
};
... ...
这段代码中我们可以看出,Request 类最主要的就是包含HTTP请求所需要的参数,主要参数为:
private final HttpUrl url;
private final String method;
private final Headers headers;
private final RequestBody body;
private final Object tag;
为了使用的方便,Request 的提供了一个Request .Builder 构造类。
public final class Request {
private final HttpUrl url;
private final String method;
private final Headers headers;
private final RequestBody body;
private final Object tag;
... ... ...
private Request(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers.build();
this.body = builder.body;
this.tag = builder.tag != null ? builder.tag : this;
}
public static class Builder {
private HttpUrl url;
private String method;
private Headers.Builder headers;
private RequestBody body;
private Object tag;
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
private Builder(Request request) {
this.url = request.url;
this.method = request.method;
this.body = request.body;
this.tag = request.tag;
this.headers = request.headers.newBuilder();
}
...
public Request build() {
if (url == null) throw new IllegalStateException("url == null");
return new Request(this);
}
... ... ...
}
}
在创建好 OkHttpClient 和 Request之后,RealCall开始登场了
final class RealCall implements Call {
private final OkHttpClient client;
... ... ...
/** The application's original request unadulterated by redirects or auth headers. */
Request originalRequest;
HttpEngine engine;
protected RealCall(OkHttpClient client, Request originalRequest) {
this.client = client;
this.originalRequest = originalRequest;
}
紧接着就是执行HTTP请求了,这里提供了两种方式,立即执行 和 加入执行队列
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain(false);
if (result == null) throw new IOException("Canceled");
return result;
} finally {
client.dispatcher().finished(this);
}
}
void enqueue(Callback responseCallback, boolean forWebSocket) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
client.dispatcher().enqueue(new AsyncCall(responseCallback, forWebSocket));
}
这里我们可以看到一个关于管理调度的标志性代码:client.dispatcher().XXX
我们看看这个是如何做到的 --- ExecutorService 线程池
public final class Dispatcher {
... ...
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
... ...
至于剩下的AsyncCall肯定是 Runnable 。这个就不贴代码了
总结下:OkHttp 的逻辑很简单,
- OkHttpClient 中包含了网络请求中所需要的所有变量参数,例如:DNS,proxy,connectTimeout 等
- Request 中包含了 请求是需要的 URL,请求方式(get/Post 等), Header, body
- OkHttpClient 与 Request 作为 RealCall 的成员变量,同时RealCall 作为一个可执行的TASK,将自身交给调度器去调度
- 调度器就是 ThreadPoolExecutor 和 SynchronousQueue 组成
如果还有不明白的,可以依据这4条再回过头看看前面的代码
到此为止,可以开始正题了 :
Retrofit 到底干什么的?-- 其实就是OkHttp的一个封装库
Retrofit 为什么要封装?
Retrofit 的框架什么样的?
为什要设计成这样?
我们在编码中有什么可以借鉴的吗?
Retrofit 使用的最大的两个技术就是: 动态代理 和 注解
动态代理:java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
先看看动态代理的相关代码
public interface PostRequest_Interface {
@POST("translate?doctype=json&jsonversion=&type=&keyfrom=&model=&mid=&imei=&vendor=&screen=&ssid=&network=&abtest=")
@FormUrlEncoded
Call<Translation1> getCall(@Field("i") String targetSentence);
}
这里就有了interface getCall
public final class Retrofit {
... ...
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method, Object... args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
Log.v("jar-filter", "method : " + method);
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
Log.v("jar-filter", "args : " + args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
上面这段代码就是动态代理了,代理了接口 getCall ( @POST("translate?doctype=json&jsonversion=&type=&keyfrom=&model=&mid=&imei=&vendor=&screen=&ssid=&network=&abtest=")这个也算在里面)
我们再回头仔细分析下代码
Retrofit.java
public <T> T create(final Class<T> service) {
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method, Object... args)
throws Throwable {
... ... ...
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
ServiceMethod serviceMethod = loadServiceMethod(method);
创建了ServiceMethod 的对象实例OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
创建了OkHttpCall 的对象实例return serviceMethod.callAdapter.adapt(okHttpCall);
返回一个ServiceMethod 的对象实例中的callAdapter.adapt
PostRequest_Interface request = retrofit.create(PostRequest_Interface.class);
//对 发送请求 进行封装(设置需要翻译的内容)
Call<Translation1> call = request.getCall("I love you");
//步骤6:发送网络请求(异步)
call.enqueue(new Callback<Translation1>() {
Proxy.newProxyInstance 函数,是在request.getCall的时候触发。
也就是说 return serviceMethod.callAdapter.adapt(okHttpCall);返回的就是Call<Translation1> call。
我拿到call后就直接enqueue。这个就说明call具有网络HTTP的功能。
loadServiceMethod
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//ServiceMethod 有一个Builder,实例的创建是通过创建者模式
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
从ServiceMethod的成员变量,可以看出ServiceMethod
- 提供了了call的工厂 ---- okhttp3.Call.Factory callFactory;
- 请求URL ---- HttpUrl baseUrl;
- 请求头信息 --- Headers headers;
final class ServiceMethod<T> {
// Upper and lower characters, digits, underscores, and hyphens, starting with a character.
static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
final okhttp3.Call.Factory callFactory;
final CallAdapter<?> callAdapter;
private final HttpUrl baseUrl;
private final Converter<ResponseBody, T> responseConverter;
private final String httpMethod;
private final String relativeUrl;
private final Headers headers;
private final MediaType contentType;
private final boolean hasBody;
private final boolean isFormEncoded;
private final boolean isMultipart;
private final ParameterHandler<?>[] parameterHandlers;
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
responseConverter = createResponseConverter();
//从代码名称我们知道这个是注解的解释
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
... ...
//这里注解 POST GET 等注解
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
if (!Void.class.equals(responseType)) {
throw methodError("HEAD method must use Void as response type.");
}
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
... ...
//可以将 注解转化为 HTTP请求时候需要的参数 httpMethod hasBodyBuilder 等
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
if (this.httpMethod != null) {
throw methodError("Only one HTTP method is allowed. Found: %s and %s.",
this.httpMethod, httpMethod);
}
this.httpMethod = httpMethod;
this.hasBodyBuilder = hasBody;
if (value.isEmpty()) {
return;
}
// Get the relative URL path and existing query string, if present.
int question = value.indexOf('?');
if (question != -1 && question < value.length() - 1) {
// Ensure the query string does not have any named parameters.
String queryParams = value.substring(question + 1);
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find()) {
throw methodError("URL query string \"%s\" must not have replace block. "
+ "For dynamic query parameters use @Query.", queryParams);
}
}
this.relativeUrl = value;
this.relativeUrlParamNames = parsePathParameters(value);
}
... ...
从上述代码我们大致的可以猜测,ServiceMethod 是为HTTP强求前期准备资源的一个类。既包括 HTTP 资源参数,也包括 callFactory。
但是到目前为止,我们还没有与OkHttp 彻底的关联上。
new OkHttpCall<>(serviceMethod, args)
final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T> serviceMethod;
private final Object[] args;
private volatile boolean canceled;
//注意这个,rawCall应该最终可以调用OkHttp 的 RealCall
private okhttp3.Call rawCall;
private Throwable creationFailure; // Either a RuntimeException or IOException.
private boolean executed;
/构造函数
OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
serviceMethod.callAdapter.adapt(okHttpCall)
首先要找到serviceMethod.callAdapter是什么
通过下面这一堆代码,我们可以知道 callAdapter 的 类就是 ExecutorCallAdapterFactory.ExecutorCallbackCall
// ServiceMethod.Builder
public ServiceMethod build() {
callAdapter = createCallAdapter();
// ServiceMethod.Builder
private CallAdapter<?> createCallAdapter() {
... ...
try {
//继续跟踪下去
return retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
//retrofit.class
public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
//retrofit.class
public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
//从一个数组或者列表中获取的, CallAdapter 可以有多个
CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
public Retrofit build() {
... ...
// 在Retrofit创建的时候会给一个默认的 platform.defaultCallAdapterFactory(callbackExecutor)
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
//就是这个
CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
if (callbackExecutor != null) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
return DefaultCallAdapterFactory.INSTANCE;
}
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
... ...
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
... ...
@Override
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Call<?>>() {
@Override public Type responseType() {
return responseType;
}
//返回的是ExecutorCallAdapterFactory.ExecutorCallbackCall
@Override public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
... ...
最后一步
call.enqueue(new Callback<Translation1>()
也就是
ExecutorCallAdapterFactory.ExecutorCallbackCall.enqueue(new Callback<Translation1>()
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");
delegate.enqueue(new Callback<T>() {
... ...
@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
//
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
//这里就是真的 realcall.enqueue
call.enqueue(new okhttp3.Callback() {
private okhttp3.Call createRawCall() throws IOException {
//创建出 OkHttp 的request
Request request = serviceMethod.toRequest(args);
//请参考 okhttp3.Call.Factory callFactory
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
okhttp3.Call.Factory callFactory = this.callFactoryBuilder;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
总结
- Retrofit 到底干什么的?
其实就是OkHttp的一个封装库,更准确说是“HTTP控件库们”的封装库,但是还没有和OKHTTP 完全脱藕 - Retrofit 为什么要封装?
因为是HTTP控件们的封装库,可以支持多个HTTP库,都有封装脱藕 - Retrofit 的框架什么样的?为什要设计成这样?
注解 @GET @POST 等,来代替请求模式和参数
ServiceMethod 是服务类,OkHttpCall 就是 OKHTTP库的实现类 - 我们在编码中有什么可以借鉴的吗?
其实注解功能可以更好的脱藕,但是代价比较大,解析代码太费劲了、
在只有Okhttp一个库的情况下,没有很好的实际意义,如果同时指出 volley 等多个HTTP库的时候,就比较有意义了。