本文是基于Retrofit2.6.0源碼的應(yīng)用于分析。
Retrofit的應(yīng)用
- 定義一個(gè)網(wǎng)絡(luò)請求接口
public interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributors(@Path("owner") String owner,
@Path("repo") String repo);
}
- 初始化一個(gè)Retrofit實(shí)例,采用構(gòu)造者模式鏈?zhǔn)秸{(diào)用
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
- 創(chuàng)建一個(gè)接口實(shí)現(xiàn)類Api:
//同步請求
GitHub github = retrofit.create(GitHub.class);
Call<List<Contributor>> call = github.contributors("square", "retrofit");
List<Contributor> contributors = call.execute().body();
//異步請求
call.enqueue(new Callback<List<Contributor>>() {
@Override
public void onResponse(Call<List<Contributor>> call, Response<List<Contributor>> response) {
}
@Override
public void onFailure(Call<List<Contributor>> call, Throwable t) {
}
});
就這樣我們完成了一次網(wǎng)絡(luò)請求。
下面我們來看下源碼中的具體實(shí)現(xiàn)。
Retrofit的源碼實(shí)現(xiàn)
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
一. 先從Retrofit.Builder開始Builder調(diào)用了
public Builder() {
this(Platform.get());
}
主要對Platform進(jìn)行了實(shí)例化在Platform的實(shí)例化中主要調(diào)用了
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
主要通過反射判斷了Retrofit是在Java平臺還是Android平臺使用,本文是假設(shè)是在Android中使用,返回了一個(gè)Android繼承Platform的實(shí)例并重構(gòu)了部分方法。
.baseUrl(API_URL)沒什么可說的主要是為Builder中的baseUrl賦值為一個(gè)HttpUrl;
.addConverterFactory(GsonConverterFactory.create())
- 添加一個(gè)gson轉(zhuǎn)換器工廠,GsonConverterFactory繼承Converter.Factory,從字面翻譯就可以理解轉(zhuǎn)換工廠,提供了3個(gè)空實(shí)現(xiàn)返回的方法。再看GsonConverterFactory的實(shí)現(xiàn)
。。。省略主要看這兩個(gè)方法
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations
, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
這兩個(gè)方法主要分別實(shí)現(xiàn)了ResponseBody轉(zhuǎn)化為實(shí)體類和實(shí)體類轉(zhuǎn)化為RequestBody。
- 再看下最后的build()方法
public Retrofit build() {
//判斷url
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
//未傳入callFactory的話默認(rèn)為OkHttpClient請求可以看出Retrofit框架可以
//使用其他網(wǎng)絡(luò)請求,它只是對網(wǎng)絡(luò)請求進(jìn)行了封裝方便使用
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
//未傳入線程池的話使用平臺默認(rèn)線程池Android平臺默認(rèn)為主線程
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 添加默認(rèn)的CallAdapter
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// 轉(zhuǎn)化工廠
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
//將添加的配置都加入轉(zhuǎn)化
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
//最后對Retrofit 進(jìn)行實(shí)例化 并賦值初始化參數(shù)。
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
二、下面看下Retrofit中重要的一步,根據(jù)傳入的接口返回一個(gè)代理實(shí)例:
GitHub github = retrofit.create(GitHub.class);
該方法調(diào)用了Retrofit中的create方法
public <T> T create(final Class<T> service) {
//先判斷是否是接口
Utils.validateServiceInterface(service);
//默認(rèn)為false
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//返回一個(gè)動態(tài)代理
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
//當(dāng)前為Android平臺
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable Object invoke(Object proxy, Method method,
@Nullable Object[] args) throws Throwable {
// 判斷是否為Object
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//sdk 24一下會直接返回flase
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//最終調(diào)用
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
至此Retrofit.create()只是生成了一個(gè)動態(tài)代理對象真正調(diào)用會是根據(jù)代理對象去調(diào)用其中方法:
Call<List<Contributor>> call = github.contributors("square", "retrofit");
根據(jù)代碼分析會調(diào)用并返回loadServiceMethod(method).invoke(args != null ? args : emptyArgs);的值,主要從緩存中取出ServiceMethod,緩存中沒有的話會調(diào)用ServiceMethod.parseAnnotations(this, method)生成:
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
ServiceMethod.parseAnnotations(this, method)中主要調(diào)用了 ServiceMethod.parseAnnotations(this, method)在方法又調(diào)用了Retrofit中的nextCallAdapter 與 nextResponseBodyConverter 得到了responseConverter與callFactory,并實(shí)例化一個(gè)SuspendForBody返回
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
Type[] parameterTypes = method.getGenericParameterTypes();
Type responseType = Utils.getParameterLowerBound(0,
(ParameterizedType) parameterTypes[parameterTypes.length - 1]);
if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
// Unwrap the actual body type from Response<T>.
responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
continuationWantsResponse = true;
} else {
// TODO figure out if type is nullable or not
// Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
// Find the entry for method
// Determine if return type is nullable or not
}
adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
adapterType = method.getGenericReturnType();
}
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
if (responseType == okhttp3.Response.class) {
throw methodError(method, "'"
+ getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (responseType == Response.class) {
throw methodError(method, "Response must include generic type (e.g., Response<String>)");
}
// TODO support Unit for Kotlin?
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
- 我們再回到Retrofit中的Retrofit.create()方法,loadServiceMethod(method)從上面分析我們知道得到的是SuspendForBody,SuspendForBody繼承了HttpServiceMethod,實(shí)際上是調(diào)用HttpServiceMethod的invoke()方法;invoke方法中實(shí)例了一個(gè)OkHttpCall對象并傳入調(diào)用了SuspendForBody的adapt方法
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
- SuspendForBody的adapt()方法,
@Override protected Object adapt(Call<ResponseT> call, Object[] args) {
call = callAdapter.adapt(call);
//noinspection unchecked Checked by reflection inside RequestFactory.
Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1];
return isNullable
? KotlinExtensions.awaitNullable(call, continuation)
: KotlinExtensions.await(call, continuation);
}
在未設(shè)置CallAdapter的情況下CallAdapter.adapt()最終調(diào)用的默認(rèn)DefaultCallAdapterFactory.get()生成的CallAdapter,為ExecutorCallbackCall。至此我們得到了Call<List<Contributor>>。
三、接下來繼續(xù)看應(yīng)用層代碼:
List<Contributor> contributors = call.execute().body();
從上面可知call是ExecutorCallbackCall類型的,call.execute()應(yīng)該調(diào)用的是ExecutorCallbackCall中的方法,實(shí)際就是調(diào)用ExecutorCallbackCall實(shí)例化時(shí)傳入的call,從上文的代碼可知call為HttpServiceMethod.invoke()方法中生成的OkHttpCall,實(shí)際調(diào)用了它的execute()方法
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}
- OkHttpCall的的execute()方法主要調(diào)用了createRawCall()根據(jù)之前構(gòu)建的請求工廠,創(chuàng)建了okhttp3.Call這也是我們調(diào)用OkhttpClient進(jìn)行請求的真實(shí)請求,之后調(diào)用了call.execute()發(fā)起請求并處理返回?cái)?shù)據(jù)。
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
.....
if (creationFailure != null) {
......
call = rawCall;
if (call == null) {
try {
//獲取Okhttp請求RealCall
call = rawCall = createRawCall();
} catch (IOException | RuntimeException | Error e) {
throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
//發(fā)起請求并處理返回體
return parseResponse(call.execute());
}
這樣我們Retrofit發(fā)起的一次同步請求就分析完成了,大體上了解了請求流程。