Retrofit 是什麼?
* Retrofit adapts a Java interface to HTTP calls by using annotations on the declared methods to
* define how requests are made. Create instances using {@linkplain Builder
* the builder} and pass your interface to {@link #create} to generate an implementation.
Retrofit 是一個對於OkHttp 的增強附件,可以直接通過註解的方式,寫網絡請求方式(GET,POST),並且具備把返回結果轉換成Java對象的擴展能力。
常見寫法:
public interface TestService {
@GET("api/weather/city/101030100/")
Call<WeatherData> getWeather2();
public class WeatherData{
public String message;
public String date;
}
@GET("api/weather/city/101030100/")
Observable<WeatherData> getWeather4();
}
實現原理
1.首先利用Java動態代理技術,根據接口生成一個代理類。
retrofit2.Retrofit#create
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
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 {
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
2. 每次調用該代理對象的方法的時候,就會走到 invoke方法裏。我們會在這個方法裏解析註解,拿到請求參數,比如請求方法,參數等信息。
loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
retrofit2.ServiceMethod#parseAnnotations
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
3.執行到loadServiceMethod(method).invoke(args != null ? args : emptyArgs);方法的地方:
retrofit2.HttpServiceMethod#invoke
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
4.然後在OkHttpCall裏面,發起真正的網絡請求
retrofit2.OkHttpCall#enqueue
@Override public void enqueue(final Callback<T> callback) {
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
});
}
5.將網絡返回的數據,根據Convert 轉換成對應的接口返回的泛型類型。
如Call <WeatherData>,會把返回結果轉成WeatherData 對象。
retrofit2.OkHttpCall#parseResponse
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
}
}
6.根據接口返回的實參類型,找到對應的實參轉換工廠,生成返回值。
如果返回時Call<WeatherData> 則返回Call對象,如Observable<WeatherData> 則返回Observable對象。
如果是Call對象,則對應的Adapter 是:
retrofit2.DefaultCallAdapterFactory#get
return new CallAdapter<Object, Call<?>>() {
public Type responseType() {
return responseType;
}
public Call<Object> adapt(Call<Object> call) {
return (Call)(executor == null ? call : new DefaultCallAdapterFactory.ExecutorCallbackCall(executor, call));
}
};
如果返回是Observable,那麼是:
hu.akarnokd.rxjava3.retrofit.RxJava3CallAdapter#adapt
@Override public Object adapt(Call<R> call) {
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
Observable<?> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
return RxJavaPlugins.onAssembly(observable);
}
最終RxJava將結果返回給調用的地方。
@Override public void onNext(Response<R> response) {
if (response.isSuccessful()) {
observer.onNext(response.body());
}
}
反射獲取返回類型:
method.getGenericReturnType()
這個方法是返回的一個全類型,比如對於 Observable<WeatherData> getWeather4(); 返回值是下面截圖中的類型:
我們可以根據返回的總類型,拿到返回的泛型類型:
ParameterizedType type
Type[] types = type.getActualTypeArguments();
比如對於 Observable<WeatherData> getWeather4(); 我們可以先根據method.getGenericReturnType() 拿到整個的返回類型,然後調用 getActualTypeArguments 方法拿到泛型類型WeatherData
總結:
單一職責:
如果我需要一個功能,那麼暴露接口出去,讓別人實現,這就具備了可拓展性。比如說結果轉換,返回結果的工廠。Retrofit只負責整個框架各個部門工作起來。
結果轉換
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
CallAdapted 負責返回類型的轉換
反射和註解
retrofit2.OkHttpCall 是真正的調用okhttp 的地方。
retrofit2.RequestFactory#create 負責生成請求的參數
Q:爲什麼要這樣寫:
public <T> T create(final Class<T> service) {
而不是
public <T> T create(final Class service) {