上一篇講解了OKHttp,本篇來介紹下它的黃金搭檔Retrofit,OKHttp+Retrofit是網絡框架的不二之選。同是Square出品,和OKHttp融合起來很是簡單。 Retofit是一個RESTful的HTTP網絡請求框架,有如下特色:html
下面講解的是官網的例子java
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
複製代碼
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
複製代碼
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> repos = service.listRepos("yeungeek");
複製代碼
默認返回的是OKHttpCall,實際真正發送請求的就是OKHttpandroid
Response<List<Repo>> list = repos.execute()
複製代碼
call.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
}
});
複製代碼
具體的請求流程能夠分爲7大步驟 git
Refrofit最大特色是使用了大量的設計模式,來進行解耦,下圖是完整的流程圖(來自Stay 在 Retrofit分析-漂亮的解耦套路): github
Retrofit retrofit = new Retrofit //1. Retrofit聲明
.Builder() //2. Builder
.baseUrl("https://api.github.com/") //3. baseUrl
.addConverterFactory(GsonConverterFactory.create()) //4. Converter Factory
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) //5. CallAdapter Factory
.build(); //6. 生成實例
複製代碼
在使用Retrofit時,首先經過建造者模式構建Retrofit。編程
public final class Retrofit {
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
final okhttp3.Call.Factory callFactory;
final HttpUrl baseUrl;
final List<Converter.Factory> converterFactories;
final List<CallAdapter.Factory> callAdapterFactories;
final @Nullable Executor callbackExecutor;
final boolean validateEagerly;
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
@Nullable Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
......
}
複製代碼
剩下的步驟都是來初始化上面的參數segmentfault
public static final class Builder {
private final Platform platform;
private @Nullable okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
private @Nullable Executor callbackExecutor;
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
......
}
複製代碼
Builder中的參數和 Retrfit 是意義一一對應的,默認構造函數進行平臺的選擇設計模式
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仍是Java8,之前版本還有對IOS平臺的支持,最新版本已經去掉了。
咱們看下Android平臺:api
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();
//默認的 CallAdapter
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);
}
}
}
複製代碼
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
......
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
//檢查合法性
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
複製代碼
把String url 轉換成HttpUrl,會對baseUrl進行合法性校驗(URL參數是否是以"/"結尾)緩存
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
複製代碼
把factory加到數據轉換器集合中,看下GsonFactory.create()具體的實現:
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
複製代碼
GsonConverterFactory使用Gson 爲初始化參數,實現responseBodyConverter
和requestBodyConverter
接口,進行真正的數據轉換處理。
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
複製代碼
把factory加到請求適配器工廠集合中,Android 平臺默認實現是ExecutorCallAdapterFactory,後面再進行詳細講解。
最後一步build生成Retrofit對象
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 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);
}
複製代碼
MainThreadExecutor
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
//建立接口實例
GitHubService service = retrofit.create(GitHubService.class);
//生成請求對象
Call<List<Repo>> repos = service.listRepos("yeungeek");
複製代碼
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.adapt(okHttpCall);
}
});
}
複製代碼
create方法中最重要的是使用了動態代理,調用接口的方法都會到Proxy的invoke方法中,在invoke方法中最重要的就是下面三行代碼
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
複製代碼
該方法讀取網絡請求接口裏的方法,根據配置生成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;
}
複製代碼
loadServiceMethod會先從cache中獲取對象,若是獲取不到,則經過建造者模式生成ServiceMethod對象。
new ServiceMethod.Builder<>(this, method).build();
複製代碼
final class ServiceMethod<R, T> {
// Upper and lower characters, digits, underscores, and hyphens, starting with a character.
static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
private final okhttp3.Call.Factory callFactory;
private final CallAdapter<R, T> callAdapter;
private final HttpUrl baseUrl;
private final Converter<ResponseBody, R> responseConverter;
private final String httpMethod;
private final String relativeUrl;
private final Headers headers;
private final MediaType contentType;
private final boolean hasBody;
private final boolean isFormEncoded;
private final boolean isMultipart;
private final ParameterHandler<?>[] parameterHandlers;
ServiceMethod(Builder<R, T> builder) {
this.callFactory = builder.retrofit.callFactory();
this.callAdapter = builder.callAdapter;
this.baseUrl = builder.retrofit.baseUrl();
this.responseConverter = builder.responseConverter;
this.httpMethod = builder.httpMethod;
this.relativeUrl = builder.relativeUrl;
this.headers = builder.headers;
this.contentType = builder.contentType;
this.hasBody = builder.hasBody;
this.isFormEncoded = builder.isFormEncoded;
this.isMultipart = builder.isMultipart;
this.parameterHandlers = builder.parameterHandlers;
}
......
}
複製代碼
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
複製代碼
public ServiceMethod build() {
//1. 從 Retrofit 中獲取網絡請求器
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?");
}
//2. 從 Refrofit 中獲取數據轉換器
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
//3. 解析網絡請求接口中方法的註解
parseMethodAnnotation(annotation);
}
.....
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.");
}
//4. 建立ParameterHandler<?>,用來解析來解析參數使用到註解
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
......
return new ServiceMethod<>(this);
}
複製代碼
createCallAdapter:根據接口方法返回類型、接口請求的註解,獲取網絡請求器
private CallAdapter<T, R> createCallAdapter() {
//獲取接口方法的返回類型
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
//獲取接口請求的註解
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
複製代碼
createResponseConverter:根據接口請求註解類型、返回類型,獲取數據數據轉換器
private Converter<ResponseBody, T> createResponseConverter() {
//獲取接口請求的註解
Annotation[] annotations = method.getAnnotations();
try {
//從Rtrofit中獲取數據轉換器
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create converter for %s", responseType);
}
}
複製代碼
parseMethodAnnotation:解析請求接口的方法註解,主要有如下標籤
parseParameter:對方法的參數註解進行解析
包含:Url,Path,Query,QueryName,QueryMap,Header,HeaderMap,Field,FieldMap,Part,PartMap,Body
private ParameterHandler<?> parseParameter(
int p, Type parameterType, Annotation[] annotations) {
ParameterHandler<?> result = null;
for (Annotation annotation : annotations) {
//參數註解解析
ParameterHandler<?> annotationAction = parseParameterAnnotation(
p, parameterType, annotations, annotation);
if (annotationAction == null) {
continue;
}
if (result != null) {
throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
}
result = annotationAction;
}
if (result == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
return result;
}
複製代碼
根據serviceMethod和請求參數,建立OkHttpCall對象
final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T, ?> serviceMethod;
private final @Nullable Object[] args;
private volatile boolean canceled;
@GuardedBy("this")
private @Nullable okhttp3.Call rawCall;
@GuardedBy("this") // Either a RuntimeException, non-fatal Error, or IOException.
private @Nullable Throwable creationFailure;
@GuardedBy("this")
private boolean executed;
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
......
}
複製代碼
serviceMethod和 args不作介紹了
根據ServiceMethod的中的callAdapter,來真正執行adapt方法
ServiceMethod的adapt方法
T adapt(Call<R> call) {
return callAdapter.adapt(call);
}
複製代碼
Android 默認的返回 ExecutorCallAdapterFactory的Call
這裏使用了靜態代理delegate,加入一些額外的操做
public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallAdapterFactory.ExecutorCallbackCall(ExecutorCallAdapterFactory.this.callbackExecutor, call);
}
......
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
複製代碼
RxJavaCallAdapterFactory返回的是Observable
@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;
}
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;
}
複製代碼
通過上面幾步操做 Call<List<Repo>> repos = service.listRepos("yeungeek")
,返回了一個 OKHttpCall 對象。
請求和 OKHttp 同樣,分爲同步請求和異步請求
execute 首先會調用ExecutorCallbackCall的execute方法:
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}
複製代碼
delegate代理實際是 OKHttpCall,最終會調用OKHttpCall的execute方法
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
......
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException | Error e) {
throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());
}
複製代碼
建立真正發送的請求Request對象
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = serviceMethod.toCall(args);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
//調用serviceMethod的 toCall 方法
okhttp3.Call toCall(@Nullable Object... args) throws IOException {
//Request 的 builder 生成 Reuqest 對象
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 callFactory.newCall(requestBuilder.build());
}
複製代碼
調用OKHttp的execute發送網絡請求,根據網絡請求結果再進行結果解析
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選擇數據轉換器,對數據進行解析後,生成Response對象返回
異步請求的流程和同步請求同樣,就是再回調處理會進行線程切換
ExecutorCallbackCall的enqueue方法
@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);
}
});
}
});
}
複製代碼
代理執行加入了線程切換到邏輯,經過callbackExecutor切換到主線程
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) {
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();
}
}
});
}
複製代碼
若是使用到RxJava,在上一節已經提到, adapt會進行適配,RxJava2CallAdapter的adapt方法中有對RxJava轉換,具體邏輯實現這邊先不展開
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
複製代碼
Retrofit真正請求網絡,底層使用的是OKHttp,Refrofit主要負責網絡請求接口的封裝,看下源碼中與HTTP相關的註解
咱們再回顧下這張流程圖:
這個模式運用的比較多,Retrofit的Builder,ServiceMethod的Builder等
設計模式能夠參考建造者模式(Bulider模式)詳解
在Retrofit 初始化,addCallAdapterFactory中的CallAdapter就是用工廠方法模式
public interface CallAdapter<R, T> {
Type responseType();
T adapt(Call<R> call);
abstract class Factory {
public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit);
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
複製代碼
實現Factory中抽象方法get,就會返回不一樣的 CallAdapter 對象 設計模式能夠參考工廠方法模式(詳解版)
Retrofit 就是一個典型的外觀類,它屏蔽了全部的實現細節,提供給使用者方便的接口,統一調用建立接口實例和網絡請求配置的方法
設計模式能夠參考外觀模式(Facade模式)詳解
主要應用CallAdapter類的adapt方法,在 Retrofit addCallAdapterFactory,對應 Factory 生成不一樣的CallAdapter,adapt就能夠調用到不一樣實現
CallAdapter就是一個Strategy,Retrofit 對應上下文(Context) 設計模式能夠參考策略模式(策略設計模式)詳解
仍是在CallAdapter獲得應用,Retrofit能夠適配Android,Java8,RxJava,guava等平臺, 不一樣平臺有不一樣的特性,addCallAdapterFactory能夠生成不一樣的平臺的CallAdapter,把不一樣平臺的特性,統一在一個接口中 設計模式能夠參考適配器模式(Adapter模式)詳解
Retrofit實例的create方法,使用了動態代理模式,網絡請求接口,都會調用到Proxy.newProxyInstance
的 invoke 方法中
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.adapt(okHttpCall);
}
});
}
複製代碼
除了使用動態代理,Retrofit 還使用了靜態代理模式,ExecutorCallbackCall的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);
}
});
}
});
}
複製代碼
設計模式能夠參考代理模式(代理設計模式)詳解
Retrofit使用了大量的設計模式,上面只是在主流過程使用到的,其餘設計模式的應用,你們能夠繼續深刻源碼去分析,總之,Refrofit框架是很是值得深刻研究的框架