Retrofit的核心原理解析
簡介
Retrofit是目前比較流行的網路框架,它封裝了okhttp作為底層的網路通訊框架, 使用動態代理方式來解析註解, 今天來扒一扒它的執行原理.
通常Retrofit的使用分為如下四步:
第一步: 定義網路介面
public interface PostRequest_Interface { @POST("translate?doctype=json&jsonversion=&type=&keyfrom=&model=∣=&imei=&vendor=&screen=&ssid=&network=&abtest=") @FormUrlEncoded Call<Translation1> getCall(@Field("i") String targetSentence); }
第二步: 建立Retrofit
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://fanyi.youdao.com/") // 設定 網路請求 Url .addConverterFactory(GsonConverterFactory.create()) //設定使用Gson解析(記得加入依賴) .build();
第三步: 建立代理物件
PostRequest_Interface request = retrofit.create(PostRequest_Interface.class);
第四步: 建立Call物件
Call<Translation1> call = request.getCall("I love you");
第五步:執行非同步網路請求
call.enqueue(new Callback<Translation1>() { //請求成功時回撥 @Override public void onResponse(Call<Translation1> call, Response<Translation1> response) { System.out.println(response.body().getTranslateResult().get(0).get(0).getTgt()); } //請求失敗時回撥 @Override public void onFailure(Call<Translation1> call, Throwable throwable) { System.out.println("請求失敗"); System.out.println(throwable.getMessage()); } });
下面通過解析原始碼來看看,整個內部實現原理是怎樣的.
我們從 第二步 程式碼開始
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://fanyi.youdao.com/") // 設定 網路請求 Url .addConverterFactory(GsonConverterFactory.create()) //設定使用Gson解析(記得加入依賴) .build();
這裡首先會例項化一個
public Builder() { this(Platform.get()); }
Builder(Platform platform) { this.platform = platform; // Add the built-in converter factory first. This prevents overriding its behavior but also // ensures correct behavior when using converters that consume all types. converterFactories.add(new BuiltInConverters()); }
其實這就是以build模式建立一個Retrofit例項. 接下來我們看下 第三步 建立代理物件
PostRequest_Interface request = retrofit.create(PostRequest_Interface.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, @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); } ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } }); }
這段程式碼主要用到了動態代理,它通過newProxyInstance返回一個T型別的動態代理物件(實際上就是PostRequest_Interface),當我們呼叫
request.getCall("I love you");
實際上會執行invoke代理方法返回一個Object. 具體來看看他是怎麼執行的呢。
if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); }
通常上面這些程式碼一般都不會執行到,所以重點來看看下面的程式碼. 分為3步來看.
1,ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); 2,OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); 3,return serviceMethod.callAdapter.adapt(okHttpCall);
1,建立一個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; }
ServiceMethod的建立是通過構造模式,建構函式中傳入了method物件,在build過程中,有個比較關鍵函式,用於對method註解進行處理
public ServiceMethod build() { //程式碼省略... for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } //程式碼省略... }
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."); } } //程式碼省略... }
2,建立OkHttpCall物件,傳入剛才建立serviceMethod和args
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) { this.serviceMethod = serviceMethod; this.args = args; }
3,用serviceMethod的callAdapter適配OkHttpCall然後返回一個T物件(此刻應該是PostRequest_Interface)
serviceMethod如何進行適配的呢,首先Retrofit建立的時候有一個介面,提供CallAdapter的建立工廠
public Builder addCallAdapterFactory(CallAdapter.Factory factory) { adapterFactories.add(checkNotNull(factory, "factory == null")); return this; }
callAdapter也是一個成員變數,通過build模式建立
final class ServiceMethod<R, T>{ this.callAdapter = builder.callAdapter; }
在Builder呼叫createCallAdapter
static final class Builder<T, R> { public ServiceMethod build() { callAdapter = createCallAdapter(); } }
private CallAdapter<T, R> createCallAdapter() { return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations); }
接著Retrofit中呼叫callAdapter,執行nextCallAdapter
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { return nextCallAdapter(null, returnType, annotations); }
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this); }
CallAdapter是從adapterFactories中獲得. adapterFactories來自於2個地方,第一是呼叫
public Builder addCallAdapterFactory(CallAdapter.Factory factory) { adapterFactories.add(checkNotNull(factory, "factory == null")); return this; }
第二是:
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) { if (callbackExecutor != null) { return new ExecutorCallAdapterFactory(callbackExecutor); } return DefaultCallAdapterFactory.INSTANCE; }
final class DefaultCallAdapterFactory extends CallAdapter.Factory { static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory(); @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) { return call; } }; } }
這個預設的CallAdapter實現很簡單,只是返回原來的call物件,沒有做任何操作. 所以說上面
return serviceMethod.callAdapter.adapt(okHttpCall);
在 第四步 中實際上返回的就是okHttpCall物件.
第五步 執行enqueue方法,實際上也是okHttpCall的enqueue方法
public void enqueue(final Callback<T> callback) { if (call == null && failure == null) { try { call = rawCall = createRawCall(); } catch (Throwable t) { failure = creationFailure = t; } } call.enqueue().... //程式碼省略... }
call來自於createRawCall
private okhttp3.Call createRawCall() throws IOException { Request request = serviceMethod.toRequest(args); okhttp3.Call call = serviceMethod.callFactory.newCall(request); return call; }
okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); }
callFactory就是OkHttpClient, 在OkHttpClient中返回一個RealCall物件
public Call newCall(Request request) { return new RealCall(this, request, false /* for web socket */); }
RealCall就是okhttp提供的物件,接下來enqueue走的就是okhttp流程了.
總的來說Retrofit只是一套解析介面註解轉換為一個okhttp call,然後走okhttp流程的註解解析框架.
最後
在這裡我總結出了網際網路公司Android程式設計師面試涉及到的絕大部分面試題及答案做成了文件和架構視訊資料免費分享給大家【 包括高階UI、效能優化、架構師課程、NDK、Kotlin、混合式開發(ReactNative+Weex)、Flutter等架構技術資料 】,希望能幫助到您面試前的複習且找到一個好的工作,也節省大家在網上搜索資料的時間來學習。
資料獲取方式:加入Android架構交流QQ群聊:513088520 ,進群即領取資料!!!
點選連結加入群聊【Android移動架構總群】: 加入群聊

資料大全