Retrofit
是什么?Retrofit
是一个遵循RESTful
设计的进行HTTP
网络请求框架的封装,是如今Android
端最火的进行网络请求的库。就像Volley
是谷歌官方对HttpURLConnection
和HttpClient
的封装,或者像Github
上许多开发者发布的对HttpURLConnection
和OkHttp
封装库同样,Retrofit
也是Square
公司发布的对OkHttp
进行了封装,所以Retrofit
中的底层网络请求是由OkHttp
来完成的。java
Retrofit
的使用步骤很简单,首先是建立一个网络请求接口描述文件。android
// 建立一个接口文件ApiService,Retrofit将每一个Http接口请求,抽象为接口中的一个方法。
public interface ApiService {
@GET("api")
Call<WeatherBean> getWeather(@Query("version") String key, @Query("cityid") String city);
}
复制代码
接着就能够建立Retrofit
对象了。算法
// 建立Retrofit对象
Retrofit retrofit = new Retrofit.Builder()
// 设置baseUrl
.baseUrl("http://www.tianqiapi.com/")
// 添加响应数据转换器工厂,这里是Gson将得到响应结果转换成Gson对象
.addConverterFactory(GsonConverterFactory.create())
// 添加网络请求适配器工厂,这里是RxJava2将Call转换成Rxjava中的Observable
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
// 建立接口实例
ApiService service = retrofit.create(ApiService.class);
// 调用接口中方法
Call<WeatherBean> responseCall = service.getWeather("v1", "101110101");
// 发送同步请求
responseCall.execute();
// 发送异步请求
responseCall.enqueue(new Callback<WeatherBean>() {
@Override
public void onResponse(Call<WeatherBean> call, Response<WeatherBean> response) {
// 主线程
String responseStr = response.body().toString();
Log.e("result", responseStr);
}
@Override
public void onFailure(Call<WeatherBean> call, Throwable t) {
// 主线程
Log.e("result", t.getMessage());
}
});
复制代码
这里稍微注意下这两行:编程
// 添加响应数据转换器工厂,这里是Gson将得到响应结果转换成Gson对象
.addConverterFactory(GsonConverterFactory.create())
// 添加网络请求适配器工厂,这里是RxJava2将Call转换成Rxjava中的Observable
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
复制代码
这里的ConverterFactory
表示数据转换器工厂,就是将接收到的响应结果数据转换成想要的类型,例如通常使用Gson
来解析服务器返回的数据,这里就添加了一个GsonConverterFactory
。CallAdapterFactory
表示的是网络请求适配器的工厂,它对应的是接口请求方法的返回类型,是将默认的ExecutorCallbackCall
转换成适配其它不一样平台所须要的类型。例如这里添加了RxJava
的适配器,那么接口中就能够写成如下这样,返回一个RxJava
中的Observable
类型。json
@GET("api")
Observable<WeatherBean> getWeather(@Query("version") String key, @Query("cityid") String city);
复制代码
本篇文章中的源码皆是基于Retrofit2.6.0
版本,下面开始经过看源码来进一步了解Retrofit
,固然这里仍是按照使用方法的顺序开始。设计模式
public Builder() {
this(Platform.get());
}
Builder(Platform platform) {
this.platform = platform;
}
复制代码
首先经过Platform.get
得到了一个Platform
,而后调用重载的构造方法。先来看看Platform
的get
方法,了解下Platform
是作什么的。api
private static final Platform PLATFORM = findPlatform();
// get方法之间返回静态成员变量PLATFORM
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();
}
复制代码
get
方法中看到直接返回了静态成员变量PLATFORM
,而PLATFORM
又是经过findPlatform
方法得到的,最后在findPlatform
方法里看到这个方法是用来作多平台兼容的,根据不一样的平台返回不一样的Platform
,这里有Android
和Java
,接下来进一步看看Android
平台下的返回的Android
这个对象。缓存
static class Android extends Platform {
// 判断是不是默认方法:API24以前统一返回false,以后调用Method类中方法判断
@IgnoreJRERequirement // Guarded by API check.
@Override boolean isDefaultMethod(Method method) {
if (Build.VERSION.SDK_INT < 24) {
return false;
}
return method.isDefault();
}
// 初始化默认的主线程执行器
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
// 初始化默认网络请求适配器工厂集合
@Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return Build.VERSION.SDK_INT >= 24
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
// 默认网络请求适配器工厂集合大小
@Override int defaultCallAdapterFactoriesSize() {
return Build.VERSION.SDK_INT >= 24 ? 2 : 1;
}
// 初始化默认数据转换器工厂集合
@Override List<? extends Converter.Factory> defaultConverterFactories() {
return Build.VERSION.SDK_INT >= 24
? singletonList(OptionalConverterFactory.INSTANCE)
: Collections.<Converter.Factory>emptyList();
}
// 默认数据转换器工厂集合大小
@Override int defaultConverterFactoriesSize() {
return Build.VERSION.SDK_INT >= 24 ? 1 : 0;
}
// MainThreadExecutor主线程执行器
static class MainThreadExecutor implements Executor {
// 主线程Handler
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
// 将传入的Runnable使用主线程Handler处理
handler.post(r);
}
}
}
复制代码
大概看一下Android
中的方法,主要是初始化Retrofit
须要的功能的。defaultCallbackExecutor
方法初始化主线程的执行器,默认状况下异步请求结束后经过它来回到主线程。defaultCallAdapterFactories
是初始化请求默认转换器工厂集合,默认建立了一个转换器工厂DefaultCallAdapterFactory
。defaultConverterFactories
是初始化默认数据转换器工厂集合。能够看出Retrofit
在这里提供了设置默认的数据转换器工厂和网络请求适配器工厂的方法,默认会调用这些方法设置默认的数据转换器工厂和网络请求适配器工厂。安全
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl));
}
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;
}
复制代码
baseUrl
方法实现很是简单就是将baseUrl
设置到Retrofit.Builder
中,参数类型为String
的方法将传入的字符串封装成了一个HttpUrl
对象,调用对应重载方法,重载方法中调用pathSegments
方法将url
分割,而后判断url
是不是以斜杠结尾,不是则抛出异常。bash
private final List<Converter.Factory> converterFactories = new ArrayList<>();
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
复制代码
该方法就是将传入的数据转换器工厂加入到成员变量中的数据转换器工厂集合中。
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
复制代码
该方法一样是将传入的网络请求适配器工厂加入到成员变量中的网络请求适配器工厂集合中。
public Retrofit build() {
// 判断baseUrl不为空
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
// 建立callFactory 默认为OkHttpClient
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// 获取默认的回调执行器,没有就会调用platform.defaultCallbackExecutor
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 建立网络请求适配器工厂集合,调用platform.defaultCallAdapterFactories加入默认网络请求适配器工厂
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// 建立数据转换器工厂集合
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// 添加内置的数据转换器工厂
converterFactories.add(new BuiltInConverters());
// 添加add方法添加的数据转换器工厂
converterFactories.addAll(this.converterFactories);
// 添加默认的数据转换器工厂
converterFactories.addAll(platform.defaultConverterFactories());
// 建立一个Retrofit对象返回
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
复制代码
build
方法中就作了许多初始化工做,包括调用了平台适配器Android
中看到的那些方法,最终建立了所需的Retrofit
对象。具体来看它作了哪些工做。首先是判断了baseUrl
是否为空,为空会抛出异常,这也对应了咱们在使用Retrofit
时必需要设置baseUrl
。接着初始化了一个callFactory
网络请求工厂,默认的就是OkHttpClient
,这也看出了Retrofit
默认底层网络请求采用的就是OkHttp
框架。而后建立了回调执行器默认会调用以前看过的Platform
中的对应方法拿到主线程的执行器。下两步其实差很少,就是建立网络请求适配器工厂集合和数据转换器工厂集合而且添加默认的网络请求适配器工厂数据转换器工厂。最后初始化工做完成后建立一个Retrofit
对象返回。这里再看一下Retrofit
的成员变量和构造函数。
public final class Retrofit {
// 一个支持并发的ConcurrentHashMap,存放请求方法的缓存,这里的ServiceMethod是解析请求方法以后的封装
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
// 网络请求工厂
final okhttp3.Call.Factory callFactory;
// baseUrl
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;
}
......
}
复制代码
这里看到构造方法中就只是作了初始化赋值操做,再来看看它的成员变量,除了以前看过的那些,这里多了一个ConcurrentHashMap
用来缓存ServiceMethod
。还有一个validateEagerly
布尔值标志,这个标志的做用是判断是否提早验证解析,先大概了解下,具体的在后面的代码里会看到。
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();
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable 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);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
复制代码
这个方法里就是Retrofit
设计的精髓,采用了外观模式和动态代理模式。也是这个方法建立了API
接口的实例。这个方法步骤有点多,一步步来看。首先看到的是validateEagerly
标志,它在这里被使用,判断为true
时会调用eagerlyValidateMethods
方法,进入eagerlyValidateMethods
方法。
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
复制代码
eagerlyValidateMethods
方法中循环遍历了由参数传入的网络请求接口类中的全部方法,而且判断方法不是默认方法且不是静态方法就调用loadServiceMethod
将该方法传入。loadServiceMethod
是一个用来解析API
接口中的方法的方法,具体点来讲就是上面示例中ApiService
中的每一个方法会被解析成一个ServiceMethod
对象并进行缓存。具体后面再看,仍是回到create
方法。
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();
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable 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);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
复制代码
eagerlyValidateMethods
默认为false
因此默认会走到return (T) Proxy.newProxyInstance
这个方法。这里使用了动态代理,invoke
方法中先判断方法是不是Object
类中方法,是就不作修改按照原样执行。再调用platform.isDefaultMethod
判断是不是默认方法,是就调用platform.invokeDefaultMethod
,该方法中抛出异常。最后是最重要的,也是解析正常接口方法走到的是最后这行return loadServiceMethod(method).invoke(args != null ? args : emptyArgs)
。正常状况下这里仍是会先调用loadServiceMethod
方法,如今再来详细看一下这个方法。
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;
}
复制代码
loadServiceMethod
中首先在serviceMethodCache
缓存中查找这个方法,若是找获得直接返回。找不到进入同步代码块,这里是DCL
单例模式,同步代码块中再次判断缓存中是否存在该方法,不存在调用ServiceMethod.parseAnnotations
方法解析方法注解得到解析结果,并将结果ServiceMethod
加入缓存。接下来看看ServiceMethod
的parseAnnotations
这个解析注解的方法。
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 解析注解得到一个RequestFactory
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);
}
复制代码
ServiceMethod
的parseAnnotations
方法中主要作了三件事。一是调用RequestFactory
的parseAnnotations
方法解析注解得到一个RequestFactory
对象。二是获取方法的返回类型并校验异常状况。三是继续调用HttpServiceMethod
的parseAnnotations
方法。先来看RequestFactory
的parseAnnotations
方法。
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
复制代码
RequestFactory
的parseAnnotations
方法中以建造者模式建立一个RequestFactory
对象。先看Builder
构造方法。
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
// 初始化获取方法上的注解,对应使用例子中的@GET
this.methodAnnotations = method.getAnnotations();
// 初始化获取方法参数类型,对应使用例子中的方法参数key、city的类型String
this.parameterTypes = method.getGenericParameterTypes();
// 初始化获取方法参数上的注解,对应使用例子中的方法参数key、city上的@Query
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
复制代码
构造函数中依旧作的是属性的初始化工做,仍是继续看其build
方法。
RequestFactory build() {
// 循环解析方法上的注解
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
// HTTP请求方法类型为空抛出异常
if (httpMethod == null) {
throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
// 注解错误抛出异常,Multipart与FormUrlEncoded必须在有请求体的post请求上使用
if (!hasBody) {
if (isMultipart) {
throw methodError(method,
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError(method, "FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
// 得到方法参数个数
int parameterCount = parameterAnnotationsArray.length;
// 解析每一个参数
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
parameterHandlers[p] =
parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
}
// 判断各类使用错误状况抛出对应异常
if (relativeUrl == null && !gotUrl) {
throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError(method, "Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError(method, "Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError(method, "Multipart method must contain at least one @Part.");
}
// 建立RequestFactory对象返回
return new RequestFactory(this);
}
复制代码
build
方法中作了四件事。一是解析方法上的注解得到HTTP
请求方法类型和其余请求头信息。二是解析方法的参数,三是抛出各类错误异常,四是建立RequestFactory
实例返回。接着简单看下parseMethodAnnotation
方法。
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);
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError(method, "@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
复制代码
该方法中主要是判断方法上注解的各类类型包括GET
、POST
等各类请求类型又或者是其余自定义请求头retrofit2.http.Headers
等,找到对应类型的解析方法进行进一步的解析。于此看来RequestFactory
中是将咱们在ApiService
中写的方法和方法参数进行解析,解析后封装成对象以供后续使用。看完RequestFactory
再回到ServiceMethod
的parseAnnotations
方法中。该方法最后又调用了HttpServiceMethod
的parseAnnotations
方法因而继续跟踪查看。
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
// 得到方法上的全部注解
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
......
} else {
// 非Kotlin方法走这边,得到方法返回类型
adapterType = method.getGenericReturnType();
}
// 调用createCallAdapter建立一个CallAdapter网络请求适配器
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
// 得到CallAdapter的响应类型
Type responseType = callAdapter.responseType();
// 是okhttp中的Response抛出异常
if (responseType == okhttp3.Response.class) {
throw methodError(method, "'"
+ getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
// 响应类型不包含泛型类型抛出异常
if (responseType == Response.class) {
throw methodError(method, "Response must include generic type (e.g., Response<String>)");
}
// TODO support Unit for Kotlin?
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
// 调用createResponseConverter方法建立ResponseConverter数据转换器
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
// 得到请求工厂
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {// 不是Kotlin方法走这里
// 建立CallAdapted传入以前建立的requestFactory、callFactory、responseConverter、callAdapter
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
复制代码
先来梳理下HttpServiceMethod
的parseAnnotations
方法的流程,该方法中主要作了这几件事。首先调用createCallAdapter
方法建立一个网络请求适配器,而后调用createResponseConverter
方法建立了响应数据转换器,接着从传入的retrofit
对象中获取到网络请求工厂callFactory
,最后经过以上这几个对象建立了一个CallAdapted
返回。下面仍是来深刻看这些方法先是createCallAdapter
。
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
// 调用retrofit.callAdapter方法
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);
}
}
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
复制代码
createCallAdapter
中调用Retrofit
类里的callAdapter
方法,进而又调用它的了nextCallAdapter
方法返回了一个CallAdapter
对象。
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
// 从网络请求适配器工厂集合中查找传入的适配器的位置
// 这里注意到nextCallAdapter方法传递的skipPast参数为null,因此这里indexOf返回-1,最终start为0
int start = callAdapterFactories.indexOf(skipPast) + 1;
// 循环遍历网络请求适配器工厂集合
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
// 调用Factory的get方法得到适配器
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
// 不为空就返回adapter
if (adapter != null) {
return adapter;
}
}
......
}
复制代码
nextCallAdapter
方法中遍历从网络请求适配器工厂集合,根据方法的返回类型调用工厂的get
得到CallAdapter
。还记得建立工厂集合时默认添加了一个DefaultCallAdapterFactory
吗?Retrofit
默认方法返回类型Call
就对应了这个工厂。进入它的get
方法查看一下。
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
}
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return executor == null
? call
: new ExecutorCallbackCall<>(executor, call);
}
};
复制代码
DefaultCallAdapterFactory
的get
方法中根据传入的方法返回类型判断,返回类型不是Call
类型就直接返回null
。类型正确会返回一个CallAdapter
。
再回到HttpServiceMethod
的parseAnnotations
方法的流程,createCallAdapter
方法以后调用createResponseConverter
方法,这两个方法的流程相似,这里就大概的看下。
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
// 一样是调用Retorfit中的方法responseBodyConverter
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);
}
}
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
// 进而调用nextResponseBodyConverter方法
return nextResponseBodyConverter(null, type, annotations);
}
// 该方法逻辑和nextCallAdapter相似
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++) {
// 调用数据转换器工厂的responseBodyConverter方法
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
......
}
复制代码
createResponseConverter
方法的逻辑流程和以前得到网络请求适配器的流程相似。都是会调用Retrofit
类中对应方法,以后再调用对应next
方法遍历数据转换器集合,从中得到合适的转换器。这里来看下经常使用的Gson
转换器的responseBodyConverter
方法。
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
复制代码
看到最终会返回一个GsonResponseBodyConverter
对象。
终于又回到Retrofit
的create
方法里了,由以前分析可知loadServiceMethod
方法最终会得到一个CallAdapted
对象,这里就会接着调用它的invoke
方法,而CallAdapted
中没有实现invoke
方法,invoke
方法在其父类HttpServiceMethod
中。
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
复制代码
invoke
方法中建立了一个Call
,实现是OkHttpCall
,注意这个Call
还不是OkHttp
中的Call
类,它仍是Retrofit
包中的类。
package retrofit2;
......
final class OkHttpCall<T> implements Call<T> {
private final RequestFactory requestFactory;
private final Object[] args;
private final okhttp3.Call.Factory callFactory;
private final Converter<ResponseBody, T> responseConverter;
private volatile boolean canceled;
// 这个rawCall才是OkHttp中的Call
@GuardedBy("this")
private @Nullable okhttp3.Call rawCall;
......
}
复制代码
能够看到这个类确实在retrofit2
包下,而且这个类中有个rawCall
成员变量,它才是OkHttp
包中的Call
。回到invoke
方法建立完OkHttpCall
对象后将其传入adapt
方法,这个方法调用的是CallAdapted
中的。
@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
复制代码
方法中又调用了callAdapter
的adapt
方法,这里的callAdapter
就是前面从适配器工厂集合中找到的,默认的就是DefaultCallAdapterFactory
的get
方法返回的。
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
......
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return executor == null
? call
: new ExecutorCallbackCall<>(executor, call);
}
};
}
复制代码
return
方法实现了CallAdapter
,其中adapt
方法返回的是一个ExecutorCallbackCall
类型,它实现了Retrofit
的Call
接口,就是最终返回的类型。至此
由上一步可知得到网络请求接口类实际使用了动态代理,因此得到的对象不是经过网络请求接口建立的对象而是它的代理对象。因此在这一步调用接口中的方法例如使用例子中的getWeather
方法时,会被动态代理对象拦截,进入它的invoke
方法,invoke
方法中的Method
参数此时就是调用的方法getWeather
,接着就会像上一步所讲的那样调用loadServiceMethod(method).invoke
方法,最终返回一个ExecutorCallbackCall
对象。接下来就是发同步和异步请求。
同步请求方法调用的是execute
方法,进入实现类ExecutorCallbackCall
的execute
方法查看。
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}
复制代码
方法里直接调用了delegate.execute
方法,这个delegate
由构造方法传入,来看构造方法。
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
复制代码
构造方法中初始化了两个成员变量,一个callbackExecutor
由以前的代码调用能够发现这个就是主线程的回调执行器,第二个delegate
就是在invoke
方法中建立的OkHttpCall
。因此这里再到OkHttpCall
里去查看它的execute
方法。
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
......
call = rawCall;
// 当前call为空
if (call == null) {
try {
// 调用createRawCall建立一个call
call = rawCall = createRawCall();
} catch (IOException | RuntimeException | Error e) {
throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
}
}
}
// 取消调用call.cancel
if (canceled) {
call.cancel();
}
// 调用call.execute方法得到OkHttp中Response再调用parseResponse方法解析响应结果返回
return parseResponse(call.execute());
}
复制代码
execute
方法中首先判断当前call
是否为空,为空则调用createRawCall
方法建立一个Call
,这个对象类型能够看到就是OkHttp
中的Call
类型,接着调用call.execute
方法得到OkHttp
返回的Response
,最后再调用parseResponse
方法解析响应结果返回。这里先看下createRawCall
方法。
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
复制代码
该方法很简单,先调用requestFactory.create
方法建立一个OkHttp
中的Request
,这里就不详细看了,requestFactory
建立时大概看过,其中封装了一个请求方法的详细信息。以后调用callFactory.newCall
方法得到了返回的Call
对象。这里的callFactory
经过前面的代码知道默认是一个OkHttpClient
。因此这个方法就至关因而执行了OkHttpClient.newCall(request)
,这就是OkHttp
的基础请求操做了。得到到OkHttp
返回的Response
后继续调用了parseResponse
方法解析,将响应结果转换成Retrofit
的Response
。
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
// 得到响应中的body
ResponseBody rawBody = rawResponse.body();
// 移除rawResponse中的body只包含状态
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
// 得到响应中的响应码
int code = rawResponse.code();
// 响应码小于200大于300表示错误
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
// 调用Response.error将body和rawResponse返回
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
// 响应码为204或者205
if (code == 204 || code == 205) {
rawBody.close();
// 响应码为204或者205调用Response.success返回响应体为空
return Response.success(null, rawResponse);
}
// 将响应体body封装成一个ExceptionCatchingResponseBody对象
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
// 调用responseConverter.convert方法转换响应结果
T body = responseConverter.convert(catchingBody);
// 调用Response.success将转换好的body和rawResponse返回
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;
}
}
复制代码
parseResponse
方法中将响应体和其余响应状态信息分离,响应体单独拿了出来进行解析。该方法里的流程为判断响应码不在200到300之间及异常状况直接调用Response.error(bufferedBody, rawResponse)
返回一个Retrofit
中的Response
,返回码为204或者205表示响应成功可是没有响应体返回,因此调用Response.success
传入的响应体为null
。除此之外其余正常状况就调用数据转换器responseConverter
的convert
方法转换响应,转换后的结果经过Response.success(body, rawResponse)
返回Retrofit
中完整的响应结果。
public static <T> Response<T> error(ResponseBody body, okhttp3.Response rawResponse) {
checkNotNull(body, "body == null");
checkNotNull(rawResponse, "rawResponse == null");
if (rawResponse.isSuccessful()) {
throw new IllegalArgumentException("rawResponse should not be successful response");
}
return new Response<>(rawResponse, null, body);
}
public static <T> Response<T> success(@Nullable T body, okhttp3.Response rawResponse) {
checkNotNull(rawResponse, "rawResponse == null");
if (!rawResponse.isSuccessful()) {
throw new IllegalArgumentException("rawResponse must be successful response");
}
return new Response<>(rawResponse, body, null);
}
复制代码
这里先看error
和success
方法,这两个方法比较相似,都是先判断是否成功,与预期不符直接抛出异常。判断完后都是建立了一个Retrofit
中所须要的相应对象Response
返回就好了。同步请求方法的流程到这里就结束了。最后再来关注下数据转换的responseConverter.convert
方法,这里调用了数据转换器工厂里的convert
方法,由于日常使用Gson
解析比较多,因此这里仍是看从Gson
对应的工厂GsonConverterFactory
得到的转换器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();
}
}
}
复制代码
GsonResponseBodyConverter
的convert
方法实现就比较简单了,就是调用Gson
中的方法了。经过构造中传入的Gson
对象建立一个JsonReader
并将响应体的字符流传入,最后调用TypeAdapter.read(jsonReader)
将请求体解析获得对应实体类。
异步和同步同样,一样调用了ExecutorCallbackCall
的对应enqueue
方法,方法中传入了一个异步回调Callback
。
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 OkHttps 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);
}
});
}
});
}
复制代码
ExecutorCallbackCall
的enqueue
方法一样进而又调用了OkHttpCall
中的enqueue
方法传入又一个回调的Callback
。在这个回调的成功onResponse
和失败onFailure
方法中都先调用了callbackExecutor.execute
进行了线程切换。callbackExecutor
就是一开始初始化时建立的MainThreadExecutor
,因此这里再次回调的callback.onFailure
和callback.onResponse
都会执行在主线程中,将响应的结果传递到外层。至此异步调用流程也结束了。最后再进入OkHttpCall
中的enqueue
方法看一下。
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
......
call = rawCall;
......
if (call == null && failure == null) {
try {
// 建立OkHttp中的Call
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
......
// 判断取消
if (canceled) {
call.cancel();
}
// 调用OkHttp中的call.enqueue
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
// 成功回调
Response<T> response;
try {
// 返回成功解析Response
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
try {
// 调用callback.onResponse
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
// 失败回调
callFailure(e);
}
private void callFailure(Throwable e) {
try {
// 调用callback.onFailure
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
});
}
复制代码
OkHttpCall
中的enqueue
方法的逻辑和同步方法的逻辑相似,一样仍是先建立OkHttp
中的Call
,再调用OkHttp
中Call
的enqueue
方法,成功得到到OkHttp
的返回结果后再一样经过parseResponse
方法解析,解析以后回调callback.onResponse
,若OkHttp
返回失败则回调callback.onFailure
。
这个模式不用找不管是OkHttp
仍是Retrofit
中都是随处可见。Retrofit
中Retrofit
这个类就是建造者模式。
建造者模式是将一个复杂对象的构建与他的表示分离,使得一样的构建过程能够建立不一样的表示。
建造者模式中有以下角色:
例:
/**
* 产品类
*/
public class Computer {
private String mCPU;
private String mMainBoard;
private String mRAM;
public void setmCPU(String mCPU) {
this.mCPU = mCPU;
}
public void setmMainBoard(String mMainBoard) {
this.mMainBoard = mMainBoard;
}
public void setmRAM(String mRAM) {
this.mRAM = mRAM;
}
}
/**
* 抽象builder类
*/
public abstract class Builder {
public abstract void buildCpu(String cpu);
public abstract void buildMainboard(String mainboard);
public abstract void buildRam(String ram);
public abstract Computer create();
}
/**
* Builder实现类
*/
public class ComputerBuilder extends Builder {
private Computer computer = new Computer();
@Override
public void buildCpu(String cpu) {
computer.setmCPU(cpu);
}
@Override
public void buildMainboard(String mainboard) {
computer.setmMainBoard(mainboard);
}
@Override
public void buildRam(String ram) {
computer.setmRAM(ram);
}
@Override
public Computer create() {
return computer;
}
}
/**
* 导演类
*/
public class Director {
Builder builder = null;
public Director(Builder builder) {
this.builder = builder;
}
public Computer createComputer(String cpu, String mainboard, String ram) {
this.builder.buildCpu(cpu);
this.builder.buildMainboard(mainboard);
this.builder.buildRam(ram);
return builder.create();
}
}
复制代码
调用:
Builder builder = new ComputerBuilder();
Director director = new Director(builder);
Computer computer = director.createComputer("i7 7700", "华硕M10H", "三星8G DDR4");
复制代码
使用场景:
- 当建立复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
- 相同的方法不一样的执行顺序。产生不一样的事件结果时。
- 多个零件头能够被装配到一个对象中,可是产生的运行结果又不相同时。
- 产品类很是复杂,或者产品类中的调用顺序不一样而产生了不一样的效能。
- 在建立一些复杂的对象时,这些对象的内部组成构件间的建造顺序是稳定的,可是对象内部组成构件面临复杂的变化。
优势:
使用建造者模式可使客户端没必要知道产品内部组成的细节。 具体的建造这类之间是相互独立的,容易扩展。 因为具体的建造者是独立的,所以能够对建造过程逐步细化,而不对其余的模块产生任何影响
缺点:
产生多余的Build对象及导演类。
Retrofit
这个类也符合外观模式。
外观模式是要求一个子系统的外部与内部的通讯必须经过一个统一的对象进行。此模式提供一个高层的接口,使得子系统更容易使用。
外观模式中有以下角色:
例:
/**
* 子系统食材类
*/
public class Food {
public void buy() {
Log.e("msg", "购买食材");
}
}
public class Wash {
public void wash() {
Log.e("msg", "清洗食材");
}
}
public class Cook {
public void cook() {
Log.e("msg", "开始作菜");
}
}
public class Serve {
public void serve() {
Log.e("msg", "作完上菜");
}
}
/**
* 外观类
*/
public class Chef {
private Food food;
private Wash wash;
private Cook cook;
private Serve serve;
public Chef() {
food = new Food();
wash = new Wash();
cook = new Cook();
serve = new Serve();
}
public void work(){
food.buy();
wash.wash();
cook.cook();
serve.serve();
}
}
复制代码
调用:
Chef chef = new Chef();
chef.work();
复制代码
使用场景:
一、构建一个有层次结构的子系统时,使用外观模式定义子系统中每层的入口点。若是子系统之间是相互依赖的,则可让其经过外观接口进行通讯。
二、子系统每每会由于不断地重构烟花而变得愈来愈复杂,大多数的模式使用时也会产生不少小的类,这个外部调用他们的用户带来了使用上的困难。能够经过外观模式提供一个简单的接口,对外隐藏子系统的具体实现并隔离变化。
三、当维护一个遗留的大型系统时,可能这个系统已经很是难以维护和拓展,可是由于它含有重要的功能,因此新的需求必须依赖于它,这时候可使用外观类,为设计粗糙或者复杂的遗留代码提供一个简单的接口,让新系统和外观类交互,而外观类负责与遗留的代码进行交互。
优势:
减小系统的相互依赖,全部的依赖都是对外观类的依赖,于子系统无关。 对用户隐藏了子系统的具体实现,减小用户对子系统的耦合。 增强了安全性。子系统中的方法若是不在外观类中开通,就没法访问到子系统中的方法。
缺点:
不符合开放封闭原则,若是业务出现变动,则可能须要直接修改外观类。
在loadServiceMethod
方法中建立ServiceMethod
时,就使用了单例模式。
单例模式是用来保证一个类仅有一个实例,而且提供一个访问他的全局访问点。
单例模式中有如下角色:
单例模式有不少种写法这里列举几种:
// 饿汉式
// 类加载时就完成了初始化,因此类加载比较慢,但获取对象的速度快,基于类加载机制,避免了多线程同步问题,可是没有达到懒加载的效果,若是始终没有使用过这个实例,就会形成内存浪费。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
// 懒汉式(线程不安全)
// 在第一次调用时初始化,节约了资源但第一次加载时反应稍慢,且多线程下不能正常工做。
public class Singleton {
private static Singleton instance ;
private Singleton() {
}
public static Singleton getInstance() {
if (instance==null){
instance=new Singleton();
}
return instance;
}
}
// 懒汉式(线程安全)
// 多线程下能正常工做,可是每次代用getInstance方法都要同步,形成没必要要的同步,而且大部分时候是用不到同步的,不建议使用。
public class Singleton {
private static Singleton instance ;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (instance == null){
instance = new Singleton();
}
return instance;
}
}
// 双重检查模式(DCL)
// 这种写法进行了两次判空,第一次为了避免必要的同步,第二次是Singleton等于null的状况下才建立实例。而且使用volatile虽然会影响性能可是保证程序的正确性。
// 资源利用率高效率高,第一次加载反应稍慢,在高并发下存在必定缺陷。会发生DCL失效。
public class Singleton {
private static volatile Singleton instance;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
// 静态内部类单例模式
// 外部类加载时并不须要当即加载内部类,内部类不被加载则不去初始化sInstance,只有调用getInstance 方法时加载SingletonHolder初始化sInstance,不只保证线程安全,也保证惟一性。推荐使用。
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHolder.sInstance;
}
private static class SingletonHolder {
private static final Singleton sInstance = new Singleton();
}
}
// 枚举单例
// 枚举的实例建立是线程安全的,而且任何状况下都是单例。
public enum Singleton {
INSTANCE;
public void doSomeThing() {
}
}
复制代码
使用场景:
确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多资源,或者某种类型对象只应该有且只有一个。
优势:
一、因为单例模式在内存中只有一个实例,减小了内存开支,特别是一个对象须要频繁的建立销毁时,并且建立或销毁时性能又没法优化,单例模式的优点就很是明显。
二、单例模式只生产一个实例全部减小了系统性能的开销,当一个对象产生须要较多的资源时,则能够经过在应用启动时直接生产一个对象,而后永久驻留内存的方式来解决。
三、单例模式能够避免对资源的多重占用,例如一个写文件操做,因为只有一个实例存在内存中,避免对同一个资源同时写操做。
四、单例模式能够在系统设置全局的访问点,优化和共享资源访问。
缺点:
一、单例模式通常没有接口,扩展很困难,若要扩展除了修改代码基本没有第二种途径能够实现。 二、Android中单例对象若是持有Context,那么很容易发生内存泄漏,所以传递给单例模式的Context,最好是Application Context。
Retrofit
中DefaultCallAdapterFactory
中的get
方法返回一个CallAdapter
就是一个适配器模式。
适配器模式是把一个类的接口变换成客户端所期待的另外一种接口,从而使本来因接口不匹配而没法在一块儿工做的两个类可以在一块儿工做。
适配器模式中有如下角色:
Target:目标角色,也就是所期待获得的接口。注意:因为这里讨论的是类适配器模式,所以目标不能够是类。
Adapee:源角色,如今须要适配的接口。
Adaper:适配器角色,适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不能够是接口,而必须是具体类。
例: 类适配器模式:
/**
* Target:须要的5伏电压
*/
public interface FiveVolt {
public int getVolt5();
}
/**
* Adaotee:220电压接口
*/
public class Volt220 {
public int getVolt220() {
return 220;
}
}
/**
* Adapter:将220伏电压转换成须要的5伏电压
*/
public class VoltAdapter implements FiveVolt {
private Volt220 volt220;
public VoltAdapter(Volt220 volt220) {
this.volt220 = volt220;
}
@Override
public int getVolt5() {
return 5;
}
}
复制代码
调用:
VoltAdapter adapter = new VoltAdapter(new Volt220());
adapter.getVolt5();
复制代码
对象适配器模式:
/**
* Target角色
*/
public interface FiveVolt {
public int getVolt5();
}
/**
* Adaotee:220电压接口
*/
public class Volt220 {
public int getVolt220() {
return 220;
}
}
/**
* 对象适配器模式
*/
public class VoltAdapter implements FiveVolt{
Volt220 mVolt220;
public VoltAdapter1(Volt220 adaptee) {
this.mVolt220 = adaptee;
}
public int getVolt220(){
return mVolt220.getVolt220();
}
@Override
public int getVolt5() {
return 5;
}
}
复制代码
调用:
VoltAdapter adapter = new VoltAdapter(new Volt220());
adapter.getVolt5()
复制代码
使用场景:
一、系统须要使用现有的类,但此类的接口不符合系统的须要,即接口不兼容。
二、想要创建一个能够重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在未来引进的类一块儿工做。 三、须要一个统一的输出接口,而输入端的类型不可预知。
优势:
更好的复用性:系统须要使用现有的类,而此类的接口不符合系统的须要。那么经过适配器模式就可让这些功能获得更好的复用。
更好的扩展性:在实现适配器功能的时候,能够调用本身开发的功能,从而天然地扩展系统的功能。
缺点:
过多的使用适配器,会让系统很是零乱,不易总体进行把握。好比,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统若是太多出现这种状况,无异于一场灾难。所以若是不是颇有必要,能够不使用适配器,而是直接对系统进行重构。
Retrofit
中在addCallAdapterFactory
时就是一种策略模式。
策略模式是定义一系列的算法,把每个算法封装起来,而且是他们可互相替换。策略模式使得算法可独立与它的客户而独立变化。
策略模式中有如下角色:
例:
/**
* 抽象策略接口
*/
public interface Calculate {
public double calculate(double num1,double num2);
}
/**
* 具体策略实现类
*/
public class AddCalculate implements Calculate {
@Override
public double calculate(double num1, double num2) {
return num1+num2;
}
}
/**
* 具体策略实现类
*/
public class SubtractCalculate implements Calculate {
@Override
public double calculate(double num1, double num2) {
return num1-num2;
}
}
/**
* 具体策略实现类
*/
public class MultiplyCalculate implements Calculate {
@Override
public double calculate(double num1, double num2) {
return num1 * num2;
}
}
/**
* 上下文角色
*/
public class Context {
private Calculate calculate;
public Context(Calculate calculate) {
this.calculate = calculate;
}
public double calculate(double num1, double num2) {
return calculate.calculate(num1, num2);
}
}
复制代码
调用:
Context context;
context = new Context(new AddCalculate());
double addResult = context.calculate(1, 1);
context = new Context(new SubtractCalculate());
double subtractResult = context.calculate(1, 1);
context = new Context(new MultiplyCalculate());
double multiplyResult = context.calculate(1, 1);
复制代码
使用场景:
一、对客户隐藏具体策略(算法)的实现细节,彼此彻底独立。 二、针对同一类型问题多种处理方式,仅仅是具体行为有差异。
三、在一个类中定义了不少行为,并且这些行为在这个类里的操做以多个条件语句的形式出现。策略模式将相关的条件分支移入它们各自的Stragety类中,以代替这些条件语句。
优势:
使用策略模式能够避免使用多重条件语句。多重条件语句不易维护,并且容易出错。
易于拓展。当要添加策略,只要实现接口就能够了。
缺点:
每一个策略都是一个类,复用性小。若是策略过多,类的数量会增多。
上层模块必须知道有哪些策略,才可以使用这些策略,这与迪米特原则相违背。
Retrofit
中的ExecutorCallbackCall
使用了装饰模式,其中真正去执行网络请求的仍是OkHttpCall
。
动态的给一个对象添加一些额外的职责,就增长功能来讲,装饰模式比生成子类更加灵活。
装饰模式中有如下角色:
例:
/**
* 抽象组件
*/
public abstract class People {
public abstract void learn();
}
/**
* 组件实现类
*/
public class XiaoMing extends People {
@Override
public void learn() {
Log.e("msg","小明学过语文");
}
}
/**
* 抽象装饰者
*/
public abstract class Teacher extends People {
private People people ;
public Teacher(People people) {
this.people = people;
}
@Override
public void learn() {
people.learn();
}
}
/**
* 装饰者具体实现类
*/
public class MathTeacher extends Teacher{
public MathTeacher(People people) {
super(people);
}
public void teachMath(){
Log.e("msg","数学老师教数学");
Log.e("msg","小明学会了数学");
}
@Override
public void learn() {
super.learn();
teachMath();
}
}
复制代码
调用:
XiaoMing xiaoMing = new XiaoMing();
MathTeacher mathTeacher = new MathTeacher(xiaoMing);
mathTeacher.learn();
复制代码
使用场景:
一、在不影响其余对象的状况下,以动态、透明地方式给单个对象添加职责。
二、须要动态的给一个对象增长功能。这些功能能够动态的撤销。
三、当不能采用继承的方式对系统进行扩充或者采用继承不利于系统若站和维护时。
优势:
经过组合非继承的方式,动态的扩展一个对象的功能,在运行时选择不一样的装饰器,从而实现不一样的行为。
有效的避免了使用继承的方式扩展一个对象的功能而带来的灵活性差、子类无限制扩张的问题。
具体组件类与具体装饰类能够独立变化。用户能够根据须要增长新的具体组件类和具体装饰类,在使用时进行组合,原有代码无需改变,符合开放封闭原则。
缺点:
由于全部对象都继承自Component,因此若是Component内部发生变化,则不可避免影响全部子类,若是基类改变,势必影响对象的内部。
比继承更加灵活机动的特性,同时也意味着装饰模式比继承更容易出错,排错也很困难,对于屡次装饰的对象,须要逐级排查,较为繁琐。因此只有在必要的时候使用装饰模式。
装饰层数不能过多,不然会影响效率。
Retrofit
中的Platform
类就是简单工厂模式。
简单工厂模式又叫作静态工厂方法模式,这是由一个工厂对象决定建立处哪种产品类的实例。
简单工厂模式中有如下角色:
例:
/**
* 手机抽象类
*/
public abstract class MobilePhone {
/**
* 查看系统版本
*/
public abstract void systemVersion();
}
/**
* 具体产品类
*/
public class IPhoneX extends MobilePhone {
@Override
public void systemVersion() {
Log.d("msg","IOS 11");
}
}
public class SamsungNote9 extends MobilePhone {
@Override
public void systemVersion() {
Log.d("msg","Android 8.0");
}
}
/**
* 手机工厂类
*/
public class MobilePhoneFactory {
public static MobilePhone createMobilePhone(String name) {
MobilePhone mobilePhone = null;
switch (name) {
case "IPhone":
mobilePhone = new IPhoneX();
break;
case "Samsung":
mobilePhone = new SamsungNote9();
break;
default:
break;
}
return mobilePhone;
}
}
复制代码
调用:
MobilePhoneFactory.createMobilePhone("IPhone").systemVersion();
复制代码
使用场景:
工厂类负责建立的对象比较少。客户只需知道传入工厂的参数,而无需关心建立对象的逻辑。
优势:
用户根据参数得到对应类的实例,无需关心建立对象的逻辑。下降了耦合性。
缺点:
可实例化的类型在编译期间已被肯定,若是须要新类型,则须要修改工厂,这违背了开放封闭原则,简单工厂须要知道全部生成类的类型,档期子类过多或者子类层次过多时不适合使用。
Retrofit
中的Converter
就是抽象工厂模式。
定义一个用于建立对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
工厂方法模式中有以下角色:
例:
/**
* 产品抽象类
*/
public abstract class Computer {
public abstract void systemVersion();
}
/**
* 具体产品类
*/
public class MacBook extends Computer {
@Override
public void systemVersion() {
Log.d("msg","MAC OS");
}
}
public class LenovoComputer extends Computer {
@Override
public void systemVersion() {
Log.d("msg","Windows10");
}
}
/**
* 抽象工厂类
*/
public abstract class ComputerFactory {
public abstract <T extends Computer> T createComputer(Class<T> clz);
}
/**
* 具体工厂
*/
public class ComputerFactoryImpl extends ComputerFactory {
@Override
public <T extends Computer> T createComputer(Class<T> clz) {
Computer computer = null;
String clzName = clz.getName();
try {
//反射生成具体计算机
computer = (Computer) Class.forName(clzName).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return (T) computer;
}
}
复制代码
调用:
ComputerFactory computerFactory = new ComputerFactoryImpl();
LenovoComputer computer = computerFactory.createComputer(LenovoComputer.class);
computer.systemVersion();
复制代码
使用场景:
一个对象族有相同的约束,则可使用抽象工厂模式。
优势:
分离接口与实现,客户端使用抽象工厂来建立须要的对象,而客户端根本就不知道具体的实现是谁,客户端只是面向产品的接口编程而已,使其从具体的产品实现中解耦,同时基于接口与实现分离,使抽象该工厂方法模式在切换产品类时更加灵活、容易。
缺点:
一是对类文件的爆炸性增长,二是不太容易扩展新的产品类。
Retrofit
中的ExecutorCallbackCall
类就是个静态代理模式,代理了OkHttpCall
。
代理模式是为其余对象提供一种代理以控制这个对象的访问。
代理模式中有如下角色:
例:
/**
* 抽象接口Subject
*/
public interface Person {
String sing(String name);
String dance(String name);
}
/**
* 委托对象 RealSubject
*/
public class ZhangYiXing implements Person {
@Override
public String sing(String name) {
return "张艺兴唱了一首"+name;
}
@Override
public String dance(String name) {
return "张艺兴跳了一支"+name;
}
}
/**
* Proxy 代理类
*/
public class JingJiRenProxy implements Person {
private Person zhangYiXing;
public JingJiRenProxy(Person zhangYiXing) {
if (zhangYiXing instanceof ZhangYiXing) {
this.zhangYiXing = zhangYiXing;
}
}
@Override
public String sing(String name) {
String money = "我是经纪人,找张艺兴唱歌要出场费100万,先付50万\n";
String sing = zhangYiXing.sing(name);
String balance = "\n尾款结清50万";
return money + sing + balance;
}
@Override
public String dance(String name) {
String money = "我是经纪人,找张艺兴跳舞要出场费200万,先付100万\n";
String dance = zhangYiXing.dance(name);
String balance = "\n尾款结清100万";
return money + dance + balance;
}
}
复制代码
调用:
JingJiRenProxy jingJiRenProxy = new JingJiRenProxy(zhangyixi);
String sing1 = jingJiRenProxy.sing("梦不落雨林");
String dance1 = jingJiRenProxy.dance("小天鹅");
复制代码
使用场景:
当没法或者不想直接访问某个对象存在困难时能够经过一个代理对象来简介访问,为了保证客户端的透明性,委托对象与代理对象须要实现相同的接口。
优势:
对代理者与被代理者进行解耦。代理对象在客户端和目标对象之间起到一个中介的做用,这样能够起到对目标对象的保护。
缺点:
对类的增长。
Retrofit
中Retrofit.create
方法中就使用了动态代理模式。
动态代理经过反射机制动态的生成代理者的对象,也就是咱们在编码阶段压根不须要知道代理谁,代理谁将会在执行阶段决定。
例:
/**
* Proxy 代理类
*/
public class SuperJingJiRenProxy {
private Person zhangYiXing;
public SuperJingJiRenProxy(Person zhangYiXing) {
if (zhangYiXing instanceof ZhangYiXing) {
this.zhangYiXing = zhangYiXing;
}
}
public Person getProxy() {
return (Person) Proxy.newProxyInstance(ZhangYiXing.class.getClassLoader(), zhangYiXing.getClass().getInterfaces(), new InvocationHandler() {
/**
* @param proxy 把代理对象本身传递进来
* @param method 把代理对象当前调用的方法传递进来
* @param args 把方法参数传递进来
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("sing")) {
String money = "我是经纪人,找张艺兴唱歌要出场费100万,先付50万\n";
String sing = (String) method.invoke(zhangYiXing, args);
String balance = "\n尾款结清50万";
return money + sing + balance;
}
if (method.getName().equals("dance")) {
String money = "我是经纪人,找张艺兴跳舞要出场费200万,先付100万\n";
String dance = (String) method.invoke(zhangYiXing, args);
String balance = "\n尾款结清100万";
return money + dance + balance;
}
return null;
}
});
}
}
复制代码
调用:
SuperJingJiRenProxy superJingJiRenProxy = new SuperJingJiRenProxy(zhangyixi);
Person proxy = superJingJiRenProxy.getProxy();
String sing2 = proxy.sing("等你下课");
String dance2 = proxy.dance("最好舞台");
复制代码
以上就是关于Retrofit
的相关总结内容。毕竟如今Retrofit
做为主流MVP+Retrofit+RxJava
这一套框架的必备成员是很是重要的,也是很是好用的。并且Retrofit
中对各类设计模式的组合使用是很是精妙的,深刻了解学习仍是颇有必要的,这对咱们自身的编码水平和架构能力都是大有裨益的。