代碼示例從github上獲取(不是自己寫的 ):https://github.com/jdsjlzx/RetrofitDemo
先看OKHttp的使用,最簡(jiǎn)單的:
//1.創(chuàng)建OkHttpClient對(duì)象
OkHttpClient okHttpClient = new OkHttpClient();
//2.創(chuàng)建Request對(duì)象,設(shè)置一個(gè)url地址(百度地址),設(shè)置請(qǐng)求方式秕豫。
Request request = new Request.Builder().url("http://www.baidu.com").method("GET",null).build();
//3.創(chuàng)建一個(gè)call對(duì)象,參數(shù)就是Request請(qǐng)求對(duì)象
Call call = okHttpClient.newCall(request);
//4.請(qǐng)求加入調(diào)度烙肺,重寫回調(diào)方法
call.enqueue(new Callback() {
//請(qǐng)求失敗執(zhí)行的方法
@Override
public void onFailure(Call call, IOException e) {
}
//請(qǐng)求成功執(zhí)行的方法
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
主要涉及3個(gè)類:
- 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網(wǎng)絡(luò)訪問的時(shí)候需要的一些參數(shù)值,為了使用方便陋葡,有些參數(shù)值由默認(rèn)值設(shè)置:
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請(qǐng)求所需要的參數(shù)彻采,主要參數(shù)為:
private final HttpUrl url;
private final String method;
private final Headers headers;
private final RequestBody body;
private final Object tag;
為了使用的方便腐缤,Request 的提供了一個(gè)Request .Builder 構(gòu)造類。
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);
}
... ... ...
}
}
在創(chuàng)建好 OkHttpClient 和 Request之后肛响,RealCall開始登場(chǎng)了
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;
}
緊接著就是執(zhí)行HTTP請(qǐng)求了岭粤,這里提供了兩種方式,立即執(zhí)行 和 加入執(zhí)行隊(duì)列
@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));
}
這里我們可以看到一個(gè)關(guān)于管理調(diào)度的標(biāo)志性代碼:client.dispatcher().XXX
我們看看這個(gè)是如何做到的 --- 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 特笋。這個(gè)就不貼代碼了
總結(jié)下:OkHttp 的邏輯很簡(jiǎn)單剃浇,
- OkHttpClient 中包含了網(wǎng)絡(luò)請(qǐng)求中所需要的所有變量參數(shù),例如:DNS,proxy虎囚,connectTimeout 等
- Request 中包含了 請(qǐng)求是需要的 URL角塑,請(qǐng)求方式(get/Post 等), Header, body
- OkHttpClient 與 Request 作為 RealCall 的成員變量淘讥,同時(shí)RealCall 作為一個(gè)可執(zhí)行的TASK圃伶,將自身交給調(diào)度器去調(diào)度
- 調(diào)度器就是 ThreadPoolExecutor 和 SynchronousQueue 組成
如果還有不明白的,可以依據(jù)這4條再回過頭看看前面的代碼
到此為止蒲列,可以開始正題了 :
Retrofit 到底干什么的窒朋?-- 其實(shí)就是OkHttp的一個(gè)封裝庫(kù)
Retrofit 為什么要封裝?
Retrofit 的框架什么樣的蝗岖?
為什要設(shè)計(jì)成這樣炼邀?
我們?cè)诰幋a中有什么可以借鑒的嗎?
Retrofit 使用的最大的兩個(gè)技術(shù)就是: 動(dòng)態(tài)代理 和 注解
動(dòng)態(tài)代理:java.lang.reflect.Proxy:這是 Java 動(dòng)態(tài)代理機(jī)制的主類剪侮,它提供了一組靜態(tài)方法來為一組接口動(dòng)態(tài)地生成代理類及其對(duì)象拭宁。
先看看動(dòng)態(tài)代理的相關(guān)代碼
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);
}
});
}
上面這段代碼就是動(dòng)態(tài)代理了,代理了接口 getCall ( @POST("translate?doctype=json&jsonversion=&type=&keyfrom=&model=&mid=&imei=&vendor=&screen=&ssid=&network=&abtest=")這個(gè)也算在里面)
我們?cè)倩仡^仔細(xì)分析下代碼
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);
創(chuàng)建了ServiceMethod 的對(duì)象實(shí)例OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
創(chuàng)建了OkHttpCall 的對(duì)象實(shí)例return serviceMethod.callAdapter.adapt(okHttpCall);
返回一個(gè)ServiceMethod 的對(duì)象實(shí)例中的callAdapter.adapt
PostRequest_Interface request = retrofit.create(PostRequest_Interface.class);
//對(duì) 發(fā)送請(qǐng)求 進(jìn)行封裝(設(shè)置需要翻譯的內(nèi)容)
Call<Translation1> call = request.getCall("I love you");
//步驟6:發(fā)送網(wǎng)絡(luò)請(qǐng)求(異步)
call.enqueue(new Callback<Translation1>() {
Proxy.newProxyInstance 函數(shù)瓣俯,是在request.getCall的時(shí)候觸發(fā)杰标。
也就是說 return serviceMethod.callAdapter.adapt(okHttpCall);返回的就是Call<Translation1> call。
我拿到call后就直接enqueue彩匕。這個(gè)就說明call具有網(wǎng)絡(luò)HTTP的功能腔剂。
loadServiceMethod
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//ServiceMethod 有一個(gè)Builder,實(shí)例的創(chuàng)建是通過創(chuàng)建者模式
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
從ServiceMethod的成員變量驼仪,可以看出ServiceMethod
- 提供了了call的工廠 ---- okhttp3.Call.Factory callFactory;
- 請(qǐng)求URL ---- HttpUrl baseUrl;
- 請(qǐng)求頭信息 --- 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();
//從代碼名稱我們知道這個(gè)是注解的解釋
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());
... ...
//可以將 注解轉(zhuǎn)化為 HTTP請(qǐng)求時(shí)候需要的參數(shù) 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);
}
... ...
從上述代碼我們大致的可以猜測(cè)掸犬,ServiceMethod 是為HTTP強(qiáng)求前期準(zhǔn)備資源的一個(gè)類。既包括 HTTP 資源參數(shù)绪爸,也包括 callFactory湾碎。
但是到目前為止,我們還沒有與OkHttp 徹底的關(guān)聯(lián)上奠货。
new OkHttpCall<>(serviceMethod, args)
final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T> serviceMethod;
private final Object[] args;
private volatile boolean canceled;
//注意這個(gè)介褥,rawCall應(yīng)該最終可以調(diào)用OkHttp 的 RealCall
private okhttp3.Call rawCall;
private Throwable creationFailure; // Either a RuntimeException or IOException.
private boolean executed;
/構(gòu)造函數(shù)
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 {
//繼續(xù)跟蹤下去
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++) {
//從一個(gè)數(shù)組或者列表中獲取的递惋, CallAdapter 可以有多個(gè)
CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
public Retrofit build() {
... ...
// 在Retrofit創(chuàng)建的時(shí)候會(huì)給一個(gè)默認(rèn)的 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);
}
//就是這個(gè)
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 {
//創(chuàng)建出 OkHttp 的request
Request request = serviceMethod.toRequest(args);
//請(qǐng)參考 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();
}
總結(jié)
- Retrofit 到底干什么的柔滔?
其實(shí)就是OkHttp的一個(gè)封裝庫(kù),更準(zhǔn)確說是“HTTP控件庫(kù)們”的封裝庫(kù)萍虽,但是還沒有和OKHTTP 完全脫藕 - Retrofit 為什么要封裝睛廊?
因?yàn)槭荋TTP控件們的封裝庫(kù),可以支持多個(gè)HTTP庫(kù)杉编,都有封裝脫藕 - Retrofit 的框架什么樣的超全?為什要設(shè)計(jì)成這樣咆霜?
注解 @GET @POST 等,來代替請(qǐng)求模式和參數(shù)
ServiceMethod 是服務(wù)類卵迂,OkHttpCall 就是 OKHTTP庫(kù)的實(shí)現(xiàn)類 - 我們?cè)诰幋a中有什么可以借鑒的嗎?
其實(shí)注解功能可以更好的脫藕绒净,但是代價(jià)比較大见咒,解析代碼太費(fèi)勁了、
在只有Okhttp一個(gè)庫(kù)的情況下挂疆,沒有很好的實(shí)際意義改览,如果同時(shí)指出 volley 等多個(gè)HTTP庫(kù)的時(shí)候,就比較有意義了缤言。