項目中的Retrofit是retrofit-2.0.0版本,我將項目中的版本和目前最新的Retrofit做對比進行源碼的閱讀
簡單使用
這是Retrofit的example:
<pre>{@code
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://api.example.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
MyApi api = retrofit.create(MyApi.class);
Response<User> user = api.getUser().execute();
}</pre>
補充一下,實現一個完整的請求過程:
//請求HTTP API接口
public interface GitHubService {
@GET("users/{user}/repos")
Call<String> listRepos(@Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://api.example.com")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(DefaultCallAdapterFactory.INSTANCE)
.build();
//Retrofit調用create對象,創建API接口對象
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> repos = service.listRepos("octocat");
//調用Call的請求方法,
call.enqueue(new Callback<String>() {
//得到相應結果
@Override
public void onResponse(Call<String> call, Response<String> response) {
String body = response.body();
// TDDO ...
}
//得到失敗結果
@Override
public void onFailure(Call<String> call, Throwable throwable) {
e.printStackTrace();
}
});
==我們可以從中總結出基本流程:==
- 創建API接口
- 構建Retrofit的Builder模式
- 添加BaseUrl,轉換工廠,適配工廠等,從而創建出Retrofit對象。
- Retrofit調用Create()創建API動態代理對象service
- 調用api接口中的方法,獲取到okhttp的call對象
- 同步或異步調用call拿到回調信息
我們從構建builder開始
Builder
Retrofit(okhttp3.Call.Factory callFactory, BaseUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories;
this.adapterFactories = adapterFactories;
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
Retrofit的構造函數需要大量的參數,可以看出基本上都是通過builder模式創建過來的。Builder是Retrofit的內部類:
public static final class Builder {
private okhttp3.Call.Factory callFactory;
private BaseUrl baseUrl;
private List<Converter.Factory> converterFactories = new ArrayList<>();
private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
private Executor callbackExecutor;
private boolean validateEagerly;
}
它會將Retrofit的構造函數中需要的參數進行默認實現或者初始化,然后返回一個Retrofit對象。
主要的參數:
baseUrl(String baseUrl)//添加基礎URL
client(OkHttpClient client)//添加OkHttpClient對象
addConverterFactory()//添加生產Converter的工廠類
addCallAdapterFactory()//添加生產CallAdapter的工廠類
Converter.Factory
Converter是我們處理HTTP請求需要的轉換類,生成RequestBody請求體和ResponseBody響應體。
/**
* Returns a {@link Converter} for converting an HTTP response body to {@code type}, or null if
* {@code type} cannot be handled by this factory. This is used to create converters for
* response types such as {@code SimpleResponse} from a {@code Call<SimpleResponse>}
* declaration.
*/
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
/**
* Returns a {@link Converter} for converting {@code type} to an HTTP request body, or null if
* {@code type} cannot be handled by this factory. This is used to create converters for types
* specified by {@link Body @Body}, {@link Part @Part}, and {@link PartMap @PartMap}
* values.
*/
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
/**
* Returns a {@link Converter} for converting {@code type} to a {@link String}, or null if
* {@code type} cannot be handled by this factory. This is used to create converters for types
* specified by {@link Field @Field}, {@link FieldMap @FieldMap} values,
* {@link Header @Header}, {@link Path @Path}, {@link Query @Query}, and
* {@link QueryMap @QueryMap} values.
*/
public Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
我們還可以創建StringConverter,將返回信息或請求信息以string的形式接收或者發送,如果在Android中引用,我們可以添加一下依賴:
compile 'com.squareup.retrofit2:converter-scalars:2.0.0-beta4'
CallAdapter.Factory
private final List<CallAdapter.Factory> adapterFactories;
這個工廠用來創建CallAdapter,實現調用和發起請求,并接受回調。
public interface CallAdapter<R,T> {
Type responseType();
T adapt(Call<R> call);
abstract class Factory{
public abstract CallAdapter<?,?> get(Type returnType,
Annotation[] annotations,
Retrofit retrofit);
}
}
有意思的是,如果我們在new Retrofit.Builder()的時候不傳入一個定義好的Callback對象(addCallAdapterFactory),最終build一個Retrofit對象的時候,會用Platform.get()
拿到一個默認callAdapter,Android環境下會使用Android
內部類去實現:
2.0.0-beta4版本:
//Retrofit
public Retrofit build() {
...
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(Platform.get().defaultCallAdapterFactory(callbackExecutor));
}
github最新版本:
//Retrofit
public Retrofit build() {
...
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
}
Platform(平臺策略):
2.0.0-beta4版本:
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
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) {
}
try {
Class.forName("org.robovm.apple.foundation.NSObject");
return new IOS();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
}
最新github版本(已經去掉了IOS平臺):
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
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();
}
}
android類:
2.0.0-beta4版本:
static class Android extends Platform {
@Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
if (callbackExecutor == null) {
callbackExecutor = new MainThreadExecutor();
}
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
最新github:
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
最后都是為了生成ExecutorCallAdapterFactory
類,這是一個callAdaper.Factory。生成的callAdapter對象在哪里調用了呢?
最新版本的retrofit.create中的返回:
return serviceMethod.callAdapter.adapt(okHttpCall);
這里的callAdapter在不使用addCallAdapterFactory的Android環境中,就是上面我們說到new ExecutorCallAdapterFactory中get方法返回的對象
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {// Retrofit動態代理serviceMethod.callAdapter.adapt(okHttpCall);調用到這里
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
接著看生成的ExecutorCallbackCall
對象:
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
這就比較清晰的看到callback就是用戶輸入的回調對象。
我們再對比一下2.0.0-beta4版本中retrofit.create中的返回:
return loadMethodHandler(method).invoke(args);
在loadMethodHandler
方法中:
MethodHandler loadMethodHandler(Method method) {
MethodHandler handler;
synchronized (methodHandlerCache) {
handler = methodHandlerCache.get(method);
if (handler == null) {
handler = MethodHandler.create(this, method);
methodHandlerCache.put(method, handler);
}
}
return handler;
}
用過一個MethodHandler
對象調用.invoke()
:
Object invoke(Object... args) {
return callAdapter.adapt(
new OkHttpCall<>(callFactory, requestFactory, args, responseConverter));
}
而拿到的這個OkHttpCall
就與上面新版的ExecutorCallbackCall
一致(其實是一個Okhttp3的callFactory對象),處理回調對象。
Retrofit.create()
其實上面callAdapter最后已經開始涉及了 create的==轉換call請求==這一步的內容。但沒有關系,我們還是繼續重新看一遍create().
走到create()這一步,我們的基本builder需要的參數已經默認或者初始化完成,并返回一個retrofit對象,這時,我們需要用retrofit對象創建一個真正處理網絡請求的接口對象,總的來說,create()這個過程就在動態代理創建API接口對象。
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, @Nullable 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);
}
//加載處理API接口方法 ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//創建OkHttpCal
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//通過對應的CallAdapter適配自定義并期望返回的Call
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
ServiceMethod
它是用來處理API接口中各種注解,和參數等,2.0.0-beta4中是Method
。我們以新版為主。在retrofit.create()中loadServiceMethod
返回serviceMethod:
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
看出也是通過Builder構建參數new ServiceMethod.Builder<>(this, method).build();
ServiceMethod.Builder中:
Builder(Retrofit retrofit, Method method) {
//Retrofit實例
this.retrofit = retrofit;
//API接口中定義的方法
this.method = method;
//API接口中方法上定義的注解--->@GET/@POST
this.methodAnnotations = method.getAnnotations();
//API接口中方法中的參數化注解
this.parameterTypes = method.getGenericParameterTypes();
//API接口中方法中的所有參數注解
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
build()
方法
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);
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
return new ServiceMethod<>(this);
}
==這個方法概括一下主要是這么幾個對象:==
- mCallAdapter //創建CallAdapter
- mResponseType //responseBody type
- parseMethodAnnotation(annotation); //解析方法注解
- mParameterHandlers //解析傳遞的參數
parseMethodAnnotation
解析方法注解的請求方式,如 "DELETE","GET","POST","PUT"等。
ParameterHandler
是將請求參數解析出來,并加入到請求中,如@PATH("xx") T xx
等。
完成以上步驟,拿到ServiceMethod,現在就可以將參數帶給toRequest,toResponse。這兩個方法將在創建okHttpCall中起到作用
/** Builds an HTTP request from method arguments. */
Request toRequest(@Nullable Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.build();
}
/** Builds a method return value from an HTTP response body. */
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
再回到create(),我們拿到初始化好的serviceMethod對象 ,去生成一個OKHttpCall:OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
跟去OkHttpCall類:
final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T, ?> serviceMethod;
private final @Nullable Object[] args;
...
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "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();
}
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
@Override public synchronized boolean isExecuted() {
return executed;
}
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else {
throw (RuntimeException) creationFailure;
}
}
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());
}
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
...
//拿到serviceMethod.toResponse處理。
}
}
構造函數中傳入了之前新建的serviceMethod和動態代理invoke方法傳遞來的args參數。異步方法enqueue將會調用createRawCall()方法,
調用serviceMethod.toRequest并創建一個request對象,然后創建一個okHttp3.Call對象,將request當做參數傳入。事實上serviceMethod.callFactory.newCall(request);
中callFactory就是OkHttpClinet。
我們在Retrofit.build()中就可以看到callFactory的創建:
public Retrofit build() {
...
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
...
}
最終,我們拿到了返回的okHttp3的call對象,實現了用okhttp3做實際網絡請求。并通過定義的serviceMethod.toResponse做返回的處理。
Finally
我們還需要回去驗證一下回調接收的消息是在主線程。也就是說我們執行call.enqueue(...)的onResponse
和onFailure
是在MainThread。
在Retrofit.build()中拿到一個CallAdapter時,看看retrofit默認定義的ExecutorCallAdapterFactory
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
platform策略中:
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
實現了一個MainThreadExecutor
的內部類,實現一個在主線程的execute:private final Handler handler = new Handler(Looper.getMainLooper());
然后我們再去看下ExecutorCallAdapterFactory中的enqueue:
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
callbackExecutor.execute
即創建ExecutorCallAdapterFactory
時傳遞過來的execute,它在主線程中執行操作。同時已經可以知道onResponse和onFailure實在主線程。
Review
- 創建API接口
- 構建Retrofit的Builder模式
添加BaseUrl,轉換工廠,適配工廠等,從而創建出Retrofit對象。 - Retrofit調用Create()創建API動態代理對象service
- 調用api接口中的方法,解析請求方式注解和請求參數,并獲取到okhttp的call對象
- 同步或異步調用call拿到回調信息