Retrofit原始碼分析
前言
Retrofit是Square公司開源的一個針對OkHttp網路請求介面進行二次封裝的框架,其網路請求的實質工作仍是由OkHttp來完成,主要工作是將網路請求通過一系列註解的形式進行拆解,並在最終執行網路請求前,將註解解析生成OkHttp請求所需的Okhttp3.Call。通過分析Retrofit原始碼,來達到深入理解Retrofit的工作流程與原理,以及學習一些值得借鑑的設計模式和啟發一些解決問題的思路。
對於原始碼中各種引數型別的相關知識,如有不理解的地方,可以參考賈博巖的兩篇文章:我眼中的Java-Type體系。
ofollow,noindex">https://www.jianshu.com/p/7649f86614d3
https://www.jianshu.com/p/e8eeff12c306基本使用
第一步:整合
implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
第二步:建立介面
public interface JianShuApi { @GET("user/{userName}/info") Observable<ResponseBody> getPersonalInfo(@Path("userName") String userName); }
第三步:配置Retrofit並例項化
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://www.jianshu.com") .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build();
第四步:獲取介面物件
JianShuApi api = retrofit.create(JianShuApi.class);
第五步:執行請求
Call<ResponseBody> call = api.getPersonalInfo("zhangSanLisi"); //非同步請求 call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { //成功回撥 } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { //失敗回撥 } }); //同步請求 try { Response<ResponseBody> response = call.execute(); } catch (IOException e) { e.printStackTrace(); }
原始碼分析
下面我們按照使用流程來分析:
1、自定義介面類
裡面的請求方法,主要通過註解的方式來實現各種引數的靈活配置。如常用的請求方式@POST @GET,新增請求引數的@Query @QueryMap,大檔案下載@Streaming,多檔案提交@Multipart,請求頭內容@Header @Headers...,具體註解使用請參考retrofit2.http裡面的內容,每個註解都有相關的註釋。
2、Retrofit.Builder
通過Retrofit.Builder構造者模式來例項化Retrofit物件,主要可配置的內容如下:
public static final class Builder { // 具體使用平臺,Platform.get()方法來獲取,這裡只分析Android private final Platform platform; // 指定用來構建Call例項的Call.Factory類 private @Nullable okhttp3.Call.Factory callFactory; // 請求的baseUrl,註釋建議我們使用相對路徑的方式來配置 // Base URL: http://example.com/api/ // Endpoint: foo/bar/ // Result: http://example.com/api/foo/bar/ private HttpUrl baseUrl; // 用於物件序列化(serialization)和反序列化(deserialization),常用GsonConverterFactory private final List<Converter.Factory> converterFactories = new ArrayList<>(); // 請求返回型別(除了Call之外),若Retrofit結合RxJava一起使用,那麼就可以新增RxJava2CallAdapterFactory // 來返回Observable型別,無縫對接RxJava private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(); // 非同步回撥執行者 private @Nullable Executor callbackExecutor; // 是否提前校驗註解方法 private boolean validateEagerly; ...... public Retrofit build() { // 必須指定baseUrl,否則異常 if (baseUrl == null) { throw new IllegalStateException("Base URL required."); } //預設OkHttpClient來建立請求Call okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } // Android平臺預設回撥在主執行緒 Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } // 預設新增一個CallAdapter和Converter // Make a defensive copy of the adapters and add the default Call adapter. List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); // Make a defensive copy of the converters. List<Converter.Factory> converterFactories = new ArrayList<>(1 + this.converterFactories.size()); // 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()); converterFactories.addAll(this.converterFactories); return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); } }
3、Retrofit.create()
public final class Retrofit { ...... public <T> T create(final Class<T> service) { // 校驗class必須是介面,並且不能繼承其他介面 Utils.validateServiceInterface(service); // 是否提前校驗方法,提前建立ServiceMethod,如果自定義的介面方法存在不合規範則丟擲異常 if (validateEagerly) { eagerlyValidateMethods(service); } // 返回一個代理物件,當呼叫api方法的時候,代理物件執行 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和請求OkHttpCall ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); // 執行adapt方法,返回指定的資料型別,具體內容會在後面CallAdapter類中說明 return serviceMethod.adapt(okHttpCall); } }); } ...... ServiceMethod<?, ?> loadServiceMethod(Method method) { ServiceMethod<?, ?> result = serviceMethodCache.get(method); if (result != null) return result; // 同步鎖 synchronized (serviceMethodCache) { //通過method物件,獲取對應快取的ServiceMethod result = serviceMethodCache.get(method); if (result == null) { // 建立ServiceMethod並存入快取 result = new ServiceMethod.Builder<>(this, method).build(); serviceMethodCache.put(method, result); } } return result; } ...... }
到這裡我們就拿到了介面代理物件物件,當呼叫介面具體方法api.getPersonalInfo("zhangSanLisi");
的時候就會執行invoke方法,獲取建立的ServiceMethod物件,執行serviceMethod.adapt(okHttpCall)
方法,這裡我們指定了請求介面卡為RxJava2CallAdapter,則返回Observable。具體參見下面RxJava2CallAdapter的adapt方法
4、ServiceMethod
這是Retrofit框架核心類 。ServiceMethod類功能是將自定義的介面方法解析適配成Http呼叫的Call,也就是生成Http請求。該類也是通過構造者模式例項化:new ServiceMethod.Builder<>(this, method).build()。
final class ServiceMethod<R, T> { ...... // 這個方法會在建立真正OkHttp請求時呼叫,即OkHttpCall類中createRawCall()方法 // 參見下面OkHttpCall分析裡enqueue方法 okhttp3.Call toCall(@Nullable Object... args) throws IOException { // 通過構造者模式RequestBuilder來建立請求Request // 裡面有使用到ServiceMethod生成的ParameterHandler物件,主要是解析不同的請求引數,大家可自行檢視原始碼分析 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]); } // 最終回通過Retrofit裡面指定的callFactory執行,這裡不指定時,預設是OkHttpClient,這裡不做進一步分析,具體可參考OkHttp原始碼。 return callFactory.newCall(requestBuilder.build()); } ...... static final class Builder<T, R> { ...... Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; // 獲取方法註解, 如@POST、@Headers this.methodAnnotations = method.getAnnotations(); // 獲取方法引數型別,如String this.parameterTypes = method.getGenericParameterTypes(); // 獲取方法引數註解,如@Query this.parameterAnnotationsArray = method.getParameterAnnotations(); } public ServiceMethod build () { /* * 一系列判斷之後呼叫的是 (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations); * 遍歷Retrofit配置時設定的callAdapterFactories,如果設定的是RxJava2CallAdapterFactory最終呼叫其get方法; * 經過一系列的返回型別判斷,最終返回CallAdapter,這裡也就是RxJava2CallAdapter */ 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?"); } /* * 獲取轉換器,也就是序列化和反序列化方式,retrofit.responseBodyConverter(responseType, annotations); * 遍歷Retrofit配置時設定的converterFactories,設定的Gson,則會呼叫GsonConverterFactory的responseBodyConverter方法; * 返回GsonResponseBodyConverter類,這裡將在後面響應回撥分析中使用到。 */ responseConverter = createResponseConverter(); for (Annotation annotation : methodAnnotations) { // 遍歷方法註解,這裡會解析自定義接口裡的方法註解並獲取對應的value,為最後建立請求okhttp3.Call準備引數 parseMethodAnnotation(annotation); } // 是否指定了請求方式 if (httpMethod == null) { throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.)."); } // 校驗請求方式與編碼方式是否不合理。FormUrlEncoded和Multipart這兩種編碼方式必須使用在有請求體的請求方式中,如:@POST,@PUT 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)."); } } // 下面是方法引數註解解析並獲取其對應的value,方法引數型別不能是泛型和萬用字元 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."); } // 這裡parseParameter方法會呼叫到Retrofit中requestBodyConverter方法 // 即GsonRequestBodyConverter類中的convert方法,進行資料序列化。 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."); } // 最終返回ServiceMethod例項物件 return new ServiceMethod<>(this); } } ...... }
GsonRequestBodyConverter
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> { private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8"); private static final Charset UTF_8 = Charset.forName("UTF-8"); private final Gson gson; private final TypeAdapter<T> adapter; GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) { this.gson = gson; this.adapter = adapter; } @Override public RequestBody convert(T value) throws IOException { Buffer buffer = new Buffer(); Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8); JsonWriter jsonWriter = gson.newJsonWriter(writer); adapter.write(jsonWriter, value); jsonWriter.close(); return RequestBody.create(MEDIA_TYPE, buffer.readByteString()); } }
5、RxJava2CallAdapter
這裡根據設定生成相對應的RxJava的被觀察者物件
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> { ...... @Override public Object adapt(Call<R> call) { // 這裡我們只考慮非同步的情況,同步基本一致。生成CallEnqueueObservable物件,call為OkHttpCall 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; } // 指定執行執行緒,RxJava2CallAdapterFactory.createWithScheduler(Scheduler)指定建立 if (scheduler != null) { observable = observable.subscribeOn(scheduler); } if (isFlowable) { return observable.toFlowable(BackpressureStrategy.LATEST); } if (isSingle) { return observable.singleOrError(); } if (isMaybe) { return observable.singleElement(); } if (isCompletable) { return observable.ignoreElements(); } return observable; } }
6、CallEnqueueObservable
RxJava的方法呼叫,當被觀察者呼叫.subscribe()
訂閱之後,會呼叫到裡面的subscribeActual()
方法。
final class CallEnqueueObservable<T> extends Observable<Response<T>> { ...... @Override protected void subscribeActual(Observer<? super Response<T>> observer) { // Since Call is a one-shot type, clone it for each new observer. Call<T> call = originalCall.clone(); retrofit2.adapter.rxjava2.CallEnqueueObservable.CallCallback<T> callback = new retrofit2.adapter.rxjava2.CallEnqueueObservable.CallCallback<>(call, observer); observer.onSubscribe(callback); // 這裡是將call加入佇列,並傳入下面的CallCallback物件,非同步請求。前面我們說過這歌call物件是OkHttpCall。 call.enqueue(callback); } private static final class CallCallback<T> implements Disposable, Callback<T> { ...... //下面是正確和失敗回撥,即呼叫onNext和onError方法 @Override public void onResponse(Call<T> call, Response<T> response) { if (disposed) return; try { observer.onNext(response); if (!disposed) { terminated = true; observer.onComplete(); } } catch (Throwable t) { ...... } } @Override public void onFailure(Call<T> call, Throwable t) { if (call.isCanceled()) return; try { observer.onError(t); } catch (Throwable inner) { ...... } } } }
7、OkHttpCall
上面call.enqueue(callback)
實際走的就是OkHttpCall的enqueue方法。
final class OkHttpCall<T> implements Call<T> { ...... @Override public void enqueue(final Callback<T> callback) { // 回撥非空判斷 checkNotNull(callback, "callback == null"); okhttp3.Call call; Throwable failure; // 同步鎖,建立真正發起網路請求的okhttp3.Call,會ServiceMethod類裡toCall方法 synchronized (this) { //這裡會對請求是否執行過判斷,也就是說代理物件方法裡生成的OkHttpCall只能執行一次 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(); } // 這裡就轉到了OkHttp網路請求框架,加入到請求佇列裡面。 // 最後回調回呼叫CallEnqueueObservable中的CallCallback,即onNext或onError方法 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) { callFailure(e); return; } try { callback.onResponse(retrofit2.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(retrofit2.OkHttpCall.this, e); } catch (Throwable t) { t.printStackTrace(); } } }); } ...... private okhttp3.Call createRawCall() throws IOException { // 呼叫的是ServiceMethod裡面的toCall()方法 okhttp3.Call call = serviceMethod.toCall(args); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; } }
下面我們看下非同步請求的回撥,這裡只分析成功回撥,失敗回撥是一樣的。
在上面enqueue方法回撥中有parseResponse(rawResponse)
這麼一行程式碼,它做的就是解析響應資料的功能。
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException { ResponseBody rawBody = rawResponse.body(); // Remove the body's source (the only stateful object) so we can pass the response along. rawResponse = rawResponse.newBuilder() .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())) .build(); 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(); } } if (code == 204 || code == 205) { rawBody.close(); return Response.success(null, rawResponse); } ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody); try { // 這裡是核心程式碼 T body = serviceMethod.toResponse(catchingBody); return Response.success(body, rawResponse); } catch (RuntimeException e) { // If the underlying source threw an exception, propagate that rather than indicating it was // a runtime exception. catchingBody.throwIfCaught(); throw e; } }
ServiceMethod類中toResponse方法:
R toResponse(ResponseBody body) throws IOException { return responseConverter.convert(body); }
這裡直接分析核心程式碼T body = serviceMethod.toResponse(catchingBody);
,通過原始碼可以看到,最終其呼叫的是Retrofit配置時設定的converterFactories類的convert方法,返回設定的物件,即反序列化響應資料。
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(); } } }
8、ExecutorCallAdapterFactory
如果我們沒有新增CallAdapterFactory請求介面卡,則會使用Android平臺預設請求介面卡ExecutorCallAdapterFactory,呼叫enqueue方法時會走ExecutorCallbackCall中的enqueue方法,然後執行OkHttpCall的enqueue方法,程式碼如下:
@Override public void enqueue(final Callback<T> callback) { checkNotNull(callback, "callback == null"); // 這裡的delegate就是OkHttpCall,最終還是走到OkHttpCall的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(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, new IOException("Canceled")); } else { callback.onResponse(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, response); } } }); } @Override public void onFailure(Call<T> call, final Throwable t) { callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, t); } }); } }); }
9、BuiltInConverters
如果沒有新增ConverterFactory,則會使用預設的BuiltInConverters進行requestBody序列化和responseBody反序列化。當然,在BuiltInConverters還存在一個重要的類ToStringConverter,不管有沒有額外新增ConverterFactory,其在ServiceMethod進行註解解析時都會使用到,具體參見ServiceMethod類中的ParameterHandler<?> parseParameterAnnotation( int p, Type type, Annotation[] annotations, Annotation annotation)
方法。
final class BuiltInConverters extends Converter.Factory { // 響應資料反序列化轉換器 @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { // 根據要求響應資料型別的不同,返回不同的converter if (type == ResponseBody.class) { return Utils.isAnnotationPresent(annotations, Streaming.class) ? retrofit2.BuiltInConverters.StreamingResponseBodyConverter.INSTANCE : retrofit2.BuiltInConverters.BufferingResponseBodyConverter.INSTANCE; } if (type == Void.class) { return retrofit2.BuiltInConverters.VoidResponseBodyConverter.INSTANCE; } return null; } // 請求體資料序列化轉化器 @Override public Converter<?, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) { return retrofit2.BuiltInConverters.RequestBodyConverter.INSTANCE; } return null; } static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> { static final retrofit2.BuiltInConverters.VoidResponseBodyConverter INSTANCE = new retrofit2.BuiltInConverters.VoidResponseBodyConverter(); @Override public Void convert(ResponseBody value) { // 不需要返回,直接close,返回null value.close(); return null; } } // RequestBody請求體轉換器 static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> { static final retrofit2.BuiltInConverters.RequestBodyConverter INSTANCE = new retrofit2.BuiltInConverters.RequestBodyConverter(); @Override public RequestBody convert(RequestBody value) { return value; } } // 流轉換器 static final class StreamingResponseBodyConverter implements Converter<ResponseBody, ResponseBody> { static final retrofit2.BuiltInConverters.StreamingResponseBodyConverter INSTANCE = new retrofit2.BuiltInConverters.StreamingResponseBodyConverter(); @Override public ResponseBody convert(ResponseBody value) { return value; } } // 容器轉換器 static final class BufferingResponseBodyConverter implements Converter<ResponseBody, ResponseBody> { static final retrofit2.BuiltInConverters.BufferingResponseBodyConverter INSTANCE = new retrofit2.BuiltInConverters.BufferingResponseBodyConverter(); @Override public ResponseBody convert(ResponseBody value) throws IOException { try { // Buffer the entire body to avoid future I/O. return Utils.buffer(value); } finally { value.close(); } } } // 轉換成String static final class ToStringConverter implements Converter<Object, String> { static final retrofit2.BuiltInConverters.ToStringConverter INSTANCE = new retrofit2.BuiltInConverters.ToStringConverter(); @Override public String convert(Object value) { return value.toString(); } } }
注意事項
通過原始碼的分析,發現一些特別需要注意的事項:
1、必須指定一個請求方式,並且不能設定兩個或兩個以上,請求方式有:@POST、@GET、@DELETE、@HEAD、@PATCH、@PUT、@OPTIONS、@HTTP;
2、Retrofit配置時設定的baseUrl與設定請求方式對應的relativeUrl,結合後要是一個合理的url,不能同時relativeUrl為null,而又不新增@Url;
3、返回資料型別不能是Retrofit中的Response
或okhttp3.Response
;
4、請求過程中生成OkHttpCall
物件,只能呼叫一次請求,不能重複呼叫;
5、預設響應資料返回ResponseBody
, 請求體@Body
可使用RequestBody
,當使用自定義實體bean時,不管做為@Body值還是作為響應資料型別都必須新增一個ConverterFactory,如常用的GsonConverterFactory
;
6、註解的使用不能胡亂搭配,比如:@Multipart和@isFormEncoded與@GET等沒有請求體的請求方式一起使用,再者添加了@Multipart,在引數裡面必須要有@Part註解。具體的可以分析ServiceMethod類中的parseParameterAnnotation
方法。
總結
這次分析以Retrofit使用流程為主線,熟悉Retrofit的工作機制以及一些注意事項。Retrofit中使用了幾種設計模式:構造者模式(Builder)、工廠模式(Factory)、策略模式(不同的CallAdapter和Converter)、觀察者模式等等,這些都是在以後的工作中可以值得借鑑的地方。還有就是註解的使用,這是一個很好的範例,基本上註解使用和解析的相關知識全部都涉及到了,可以閱讀一下文章開始推薦的Java-Type體系,是兩篇值得一讀好文章。
以上就是本次分析的全部內容,由於個人能力有限,如有不足或錯誤的地方,敬請諒解。