Retrofit2.5如何傳送請求和處理響應?
Retrofit對請求方法的解析
Retrofit對我們在介面類中定義的方法是如何轉換成了請求,又如何處理響應。這一切都在它的loadServiceMethod 方法中
程式碼基於Retrofit2.5.0
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
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);//這裡就是對請求的解析,也就是我們定義的介面方法 Type returnType = method.getGenericReturnType();//獲取返回的型別 //省略無關程式碼 return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); }
RequestFactory.parseAnnotations 這個方法就是對我們定義的介面方法的解析,在裡面解析註解和使用反射得到了關於請求的所有資訊。
響應的處理
在完成了對請求的處理後構建了RequestFactory類,這個類裡面包含了請求的所有資訊:
final class RequestFactory { static RequestFactory parseAnnotations(Retrofit retrofit, Method method) { return new Builder(retrofit, method).build(); } private final Method method; private final HttpUrl baseUrl; final String httpMethod; private final @Nullable String relativeUrl; private final @Nullable Headers headers; private final @Nullable MediaType contentType; private final boolean hasBody; private final boolean isFormEncoded; private final boolean isMultipart; private final ParameterHandler<?>[] parameterHandlers;
接下來繼續來看ServiceMethod的parseAnnotations剩下的語句
ServiceMethod.parseAnnotations
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) { //省略無關程式碼 return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);//對響應的處理 }
HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) { CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);//建立請求介面卡 Type responseType = callAdapter.responseType(); //省略無關程式碼 Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType);//建立響應資料轉換器(Gson) okhttp3.Call.Factory callFactory = retrofit.callFactory;//Okhttp請求客戶端 return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter); }
建立請求介面卡CallAdapter
首先進入第一行HttpServiceMethod.createCallAdapter
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter( Retrofit retrofit, Method method) { Type returnType = method.getGenericReturnType();//獲取返回的型別 Annotation[] annotations = method.getAnnotations();//獲取註解 try { //noinspection unchecked return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(method, e, "Unable to create call adapter for %s", returnType); } }
在獲取了方法的返回型別和註解之後,呼叫
retrofit.callAdapter
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { return nextCallAdapter(null, returnType, annotations); } public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { //空判斷 checkNotNull(returnType, "returnType == null"); checkNotNull(annotations, "annotations == null"); int start = callAdapterFactories.indexOf(skipPast) + 1; for (int i = start, count = callAdapterFactories.size(); i < count; i++) { CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this); if (adapter != null) { return adapter; } } }
這裡面是一個迴圈獲取請求介面卡工廠陣列callAdapterFactories ,在retrofit建立的時候,我們可以知道往這個數組裡面加的是Android 平臺預設的ExecutorCallAdapterFactory
public Retrofit build() { List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor)); } static class Android extends Platform { @Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories( @Nullable Executor callbackExecutor) { if (callbackExecutor == null) throw new AssertionError(); //這裡可以看到返回的類 ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor); return Build.VERSION.SDK_INT >= 24 ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory) : singletonList(executorFactory); } }
在剛才的迴圈裡,呼叫了它的get 方法,實際就是呼叫
ExecutorCallAdapterFactory.get
@Override public @Nullable 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 new ExecutorCallbackCall<>(callbackExecutor, call); } }; }
我們定義的返回型別一般是泛型的形式,如Call<Response>或者Observable<Response> ,所以Utils.getCallResponseType就是取出泛型裡面的型別。最後將得到的型別傳入新建的CallAdapter
return new CallAdapter<Object, Call<?>>() { @Override public Type responseType() { return responseType; } @Override public Call<Object> adapt(Call<Object> call) { return new ExecutorCallbackCall<>(callbackExecutor, call); } };
自此就完成了CallAdapter 的建立,這裡記住它的adapt 方法,裡面是返回的ExecutorCallbackCall ,這個後面會呼叫,再來繼續看。
HttpServiceMethod的parseAnnotations第一行程式碼到此就完了,繼續往下執行:
建立響應資料轉換器(如Gson)和請求客戶端
HttpServiceMethod.parseAnnotations
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) { CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method); Type responseType = callAdapter.responseType();//獲取具體的響應型別 //省略無關程式碼 Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType); okhttp3.Call.Factory callFactory = retrofit.callFactory; return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter); }
注意這裡傳給responseConverter的responseType是我們剛才獲取Call泛型裡面的具體型別,也就是我們想要拿到的實體類型別。
這個過程跟剛才建立CallAdapter的過程很像,就連方法名都很像,所以來看看createResponseConverter 方法:
HttpServiceMethod.createResponseConverter
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter( Retrofit retrofit, Method method, Type responseType) { Annotation[] annotations = method.getAnnotations(); try { return retrofit.responseBodyConverter(responseType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(method, e, "Unable to create converter for %s", responseType); } }
通過method的getAnnotations拿到註解列表,然後跟返回型別傳入responseBodyConverter方法:
retrofit.responseBodyConverter
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) { return nextResponseBodyConverter(null, type, annotations); } public <T> Converter<ResponseBody, T> nextResponseBodyConverter( @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) { checkNotNull(type, "type == null"); checkNotNull(annotations, "annotations == null"); int start = converterFactories.indexOf(skipPast) + 1; for (int i = start, count = converterFactories.size(); i < count; i++) { Converter<ResponseBody, ?> converter = converterFactories.get(i).responseBodyConverter(type, annotations, this); if (converter != null) { //noinspection unchecked return (Converter<ResponseBody, T>) converter; } }
這個過程簡直跟剛才建立CallAdapter的過程一模一樣,也是迴圈從converterFactories取出Converter,根據之前Retrofit的建立時我們傳入的是GsonConverterFactory ,所以是呼叫的它的responseBodyConverter 方法:
GsonConverterFactory.responseBodyConverter
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new GsonResponseBodyConverter<>(gson, adapter); }
這裡的程式碼就很面熟了,通過TypeToken 獲取型別,之後返回一個Gson解析器,它的convert就是呼叫Gson進行泛型的解析。
GsonResponseBodyConverter
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> { private final Gson gson; private final TypeAdapter<T> adapter; GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) { this.gson = gson; this.adapter = adapter; } @Override public T convert(ResponseBody value) throws IOException { JsonReader jsonReader = gson.newJsonReader(value.charStream()); try { T result = adapter.read(jsonReader); if (jsonReader.peek() != JsonToken.END_DOCUMENT) { throw new JsonIOException("JSON document was not fully consumed."); } return result; } finally { value.close(); } } }
到這裡就完成了響應字串的解析器的建立,接下來會執行
okhttp3.Call.Factory callFactory = retrofit.callFactory; return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
建立okhttp請求的客戶端,這裡命名為callFactory,在Retrofit建立的時候我們傳入的okhttpClient就是賦值給了callFactory,最後將建立好的物件傳入HttpServiceMethod返回。
到此為止就執行完了HttpServiceMethod的parseAnnotations方法,在這個方法裡面,建立了幾個重要的東西
- 對請求和響應做具體處理的CallAdapter類,具體為ExecutorCallAdapterFactory ,這裡要注意它的adapt 方法返回ExecutorCallbackCall 類
- 響應資料解析工廠Converter,具體為GsonResponseBodyConverter
- okhttp請求客戶端
傳送請求
終於到了這一步了,在做好了所有的準備工作之後,最終Retrofit怎麼來發送請求呢,首先一步步回到最開始的地方: 在HttpServiceMethod.parseAnnotations方法是在ServiceMethod的parseAnnotations呼叫的
ServiceMethod.parseAnnotations
abstract class ServiceMethod<T> { 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); } abstract T invoke(Object[] args); }
然後ServiceMethod.parseAnnotations方法是在Retrofit的loadServiceMethod 呼叫的
然後loadServiceMethod是在Retrofit的create 方法裡面建立動態代理的invoke呼叫的
Retrofit.create
public <T> T create(final Class<T> service) { //省略無關程式碼 return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { //省略無關程式碼 @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { //省略無關程式碼 return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } }); }
可以看到,在loadServiceMethod 之後呼叫了invoke 方法,也就是ServiceMethod的invoke方法,點進去之後發現它是個ServiceMethod是個抽象類 ,它的invoke需要實現類來重寫:
abstract class ServiceMethod<T> { abstract T invoke(Object[] args); }
ServiceMethod類只有一個實現類,也就是我們剛才看到過的HttpServiceMethod ,所以實際上呼叫的是它的invoke方法:
HttpServiceMethod.invoke
@Override ReturnT invoke(Object[] args) { return callAdapter.adapt( new OkHttpCall<>(requestFactory, args, callFactory, responseConverter)); }
在這裡只有一行程式碼,實際上是呼叫callAdapter.adapt,那這個callAdapter是什麼呢?剛才我們已經知道它是ExecutorCallAdapterFactory 建立的,然後在建立的callAdapter的adapt 方法返回ExecutorCallbackCall 類,所以來看看這個類:
ExecutorCallbackCall是ExecutorCallAdapterFactory的靜態內部類
ExecutorCallbackCall
static final class ExecutorCallbackCall<T> implements Call<T> { final Executor callbackExecutor; final Call<T> delegate; 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); } }); } }); } @Override public boolean isExecuted() { return delegate.isExecuted(); } @Override public Response<T> execute() throws IOException { return delegate.execute(); } @Override public void cancel() { delegate.cancel(); } @Override public boolean isCanceled() { return delegate.isCanceled(); } @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone. @Override public Call<T> clone() { return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone()); } @Override public Request request() { return delegate.request(); } }
在這個類裡面,我們就看到了很多很熟悉的方法,enqueue方法傳送請求,實際的請求和處理就是在這裡面,但是還有疑惑就是具體的處理我們還是沒看到,callbackExecutor 和delegate 這兩個熟悉才是關鍵所在:
callbackExecutor
這個是在ExecutorCallAdapterFactory的構造方法中傳入的,它的構造方法又是在Platform的defaultCallAdapterFactories 方法中呼叫的,看到Platform,自然可以想到它的Android 平臺類,所以這個callbackExecutor實際上是MainThreadExecutor
@Override public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); } static class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { handler.post(r); } }
其實程式碼很簡單,使用了我們最常用的Handler ,讓程式碼在主執行緒中執行,也就是我們通常做的在子執行緒請求網路,主執行緒中更新UI。
delegate
delegate實際是在HttpServiceMethod的invoke方法裡傳入:
@Override ReturnT invoke(Object[] args) { return callAdapter.adapt( new OkHttpCall<>(requestFactory, args, callFactory, responseConverter)); }
實際上是OkHttpCall 這個類,這個類裡面就是傳送請求和處理響應的具體處理,程式碼很多,我們只看看構造方法和enqueue
OkHttpCall(RequestFactory requestFactory, Object[] args, okhttp3.Call.Factory callFactory, Converter<ResponseBody, T> responseConverter) { this.requestFactory = requestFactory;//請求工廠,裡面包含了請求的所有資訊 this.args = args;//引數 this.callFactory = callFactory;//請求客戶端,okhttp this.responseConverter = responseConverter;//響應的json解析器(Gson) }
OkHttpCall.enqueue
@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) { throwIfFatal(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) { Response<T> response; try { response = parseResponse(rawResponse); } catch (Throwable e) { throwIfFatal(e); callFailure(e); return; } try { callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { t.printStackTrace(); } } @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(); } } }); }
程式碼其實很簡單,就是使用okhttp請求,然後在響應方法onResponse做相應的解析和處理,最後完成網路請求。
總結
Retrofit對響應的解析大概可分為
- 建立處理介面卡CallAdapter,具體實現類為ExecutorCallbackCall ,在這裡面進行傳送請求和處理響應等相關的操作,最終是呼叫okhttp進行網路請求
- 建立響應資料轉換器Converter,具體實現類為GsonResponseBodyConverter ,用於對返回json資料的解析,這個是我們自己傳入的Gson解析工廠,Retrofit也支援其他的第三方解析庫
- 傳送請求,具體的操作類是OkHttpCall 來發送請求和處理響應,MainThreadExecutor 來做回撥的處理,在主執行緒中處理已經轉化好的實體類。