说明:
本文的源码分析较为粗浅,和其他源码“解析”的文章相比并未特别详细,个人觉得看别人的源码,将整体的思路和大框架了解了,理解了其思想原理足矣
很重要的一点:
一定要带着质疑别人所谓的的“解析”去分析,一定要结合源码有自己的理解,不能完全相信他人的观点,即便是所谓的“大神”,人,总有犯错的时候。
如果文中有哪里不对的地方,请多指教。
从调用的流程开始分析

一、Retrofit的初始化
// 初始化配置Retrofit
retrofit = new Retrofit.Builder()
.baseUrl(AppConfig.BASE_URL)
//可设置自定义的client
.client(getOkHttpClient())
//可设置自定义的执行类CallAdapterFactory,可多个
.addCallAdapterFactory(new CustCallAdapterFactory())
//可设置自定义的解析类ConverterFactory,可多个
.addConverterFactory(new CustConvertFactory())
.build();
private OkHttpClient getOkHttpClient() {
if (okHttpClient == null) {
okHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(15 * 1000, TimeUnit.MILLISECONDS)
.readTimeout(15 * 1000, TimeUnit.MILLISECONDS)
.retryOnConnectionFailure(true)
.addInterceptor(xxxInterceptor)
.build();
}
return okHttpClient;
}
- 这里对Retrofit进行初始化,是通过构造者模式进行构建相关的参数数据
-
addConverterFactory:为对象的序列化和反序列化添加转换器工厂 -
addCallAdapterFactory:添加调用适配器工厂以支持除Call之外的服务方法返回类型
1、baseUrl:
-
baseUrl的方法有多个重载,最终通过构造HttpUrl传入,一直传递给
okhttp3.Request中public Builder baseUrl(HttpUrl baseUrl) //最终的调用 public Builder baseUrl(String baseUrl)Request build() { HttpUrl url; HttpUrl.Builder urlBuilder = this.urlBuilder; if (urlBuilder != null) { url = urlBuilder.build(); } else { // No query parameters triggered builder creation, just combine the relative URL and base URL. url = baseUrl.resolve(relativeUrl); if (url == null) { throw new IllegalArgumentException( "Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl); } } //省略好多... return requestBuilder .url(url) .method(method, body) .build(); } -
如何动态切换Retrofit的BaseURL?
Retrofit中接收的baseUrl(String),最终是作为HttpUrl(okhttp3包里的)的类型参数传入的,在HttpUrl中有个host的字段,可以通过反射进行修改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; }
二、Retrofit的请求和响应
// ① 获取接口实现
GitHubService service = retrofit.create(GitHubService.class);
// ② 调用(下面同步或异步请求选其一)
Call<List<Repo>> repos = service.listRepos("octocat");
// ③ 同步请求
Response<ResponseBody> res = repos.execute();
// ③ 异步请求
repos.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
// 或者通过使用Observable,需要在初始化时进行配置:
// addCallAdapterFactory(RxJava3CallAdapterFactory.createSynchronous())
Observable<UserBean> call = mRetrofit.create(GitHubService.class).getUserData();
call.subsribe(Xxx)
1、接口的实现类:
从Retrofit 的示例来看,只需要一个接口及接口方法即可,调用者无需实现接口的具体实现类,就可以调用其内的方法,接口的实现类是从哪来的呢?
通过Retrofit#create 方法获得了接口的实现类,其内部是通过 动态代理(模式) Proxy.newProxyInstance 来实现的:
public <T> T create(final Class<T> service) {
validateServiceInterface(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);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method) //对default方法进行判断
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
-
动态代理
Proxy.newProxyInstance的参数和返回结果:-
classLoader[参数]:类加载器会产生新类(实现的是传入的接口) -
class[][参数]:新类实现的接口,传进来(放到数组中) -
invocationHandler 接口[参数]:执行方法体 -
T[返回值]:一个封装了请求参数的接口的类,来发起网络请求
通过字节码(或打印其getClass())可得出类似于:class com.sun.proxy.$Proxy0
-
-
获取(动态代理)接口的实例对象
在Proxy中,通过newProxyInstance获取对象时,其中维护了一个代理类的缓存集合proxyClassCache【是WeakCache,其内部通过ConcurrentMap进行实际的缓存】,从此缓存中获取生成的接口实现类。
而实现类的创建,是通过其固定的名称组装的类名://Proxy中: //固定规则 if (proxyPkg == null) { // if no non-public proxy interfaces, use com.sun.proxy package proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; //com.sun.proxy } String proxyName = proxyPkg + proxyClassNamePrefix + num; byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags); try { //这里返回结果,加载byte[]来获取对象 return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { throw new IllegalArgumentException(e.toString()); } -
InvocationHandler#invoke内部解析:
1】Retrofit#loadServiceMethod:
在每次调用请求接口方法的时候,每次都会通过调用invocationHandler中的loadServiceMethod方法,
在loadServiceMethod方法内部,会解析得到具体的接口方法的实现(如例子中的listRepos),进行调用invoke(args)执行方法,发起网络请求。
2】platform.isDefaultMethod(method)
invocationHandler中对default方法进行了判断。如果是默认方法则对默认方法进行调用
default是Java8的特性,在接口中可定义一些默认的方法:interface GithubApi { //默认方法 default void hello() { //do something... } }
注:其中
loadServiceMethod返回的类型是ServiceMethod,其具体实现类为HttpServiceMethod。(似乎在之前的版本,2.2.0吧,ServiceMethod是final的,没有实现类。)
2、解析并装配参数(Okhttp请求)
在发送请求的时候,需要传入一些参数,对于Retrofit ,其请求的参数是放到注解上的,那它是如何对其进行解析的呢?是通过loadServiceMethod 方法内部对接口方法的注解及参数的解析而得。
-
Retrofit#loadServiceMethod
在loadServiceMethod方法中,通过传入的Method类型的参数来封装成ServiceMethod对象。
获取具体的ServiceMethod对象流程(复用):
1】先从serviceMethodCache缓存集合(ConcurrentHashMap)中根据Method取出ServiceMethod对象,有则直接返回
2】若无,加锁,通过ServiceMethod#parseAnnotations解析方法的注解信息,创建对应的接口方法的实现;
并缓存到集合中
ConcurrentHashMap是个线程安全的集合(数组 + 链表 + 红黑树),因为网络请求都是在线程中去做的ServiceMethod对象(具体实现为HttpServiceMethod)中封装了各种解析工厂类等请求和响应的数据类信息(CallAdapter和Converter等等)。
ServiceMethod#parseAnnotations
1】通过RequestFactory获取接口方法(如listRepos方法)上的注解和参数等信息
如:baseUrl、headers等等
2】获取返回值的泛型参数类型:
method.getGenericReturnType()
3】最后返回具体的注解信息结果:
HttpServiceMethod.parseAnnotations
通过HttpServiceMethod(ServiceMethod的实现类)进行返回值包装类和返回值类的处理。HttpServiceMethod#parseAnnotations
1】通过HttpServiceMethod#createCallAdapter得到CallAdapter对象,方法内部根据参数进行匹配而得
2】通过createResponseConverter得到Converter对象,方法内部根据参数匹配而得
3】通过CallAdapter和Converter等对象构造出HttpServiceMethod具体实现的子类对象并返回
① 若不是kotlin协程的方法,则返回CallAdapted对象
② 否则返回协程方法相关的对象实例:SuspendForResponse或SuspendForBodyServiceMethod#invoke(args)
执行接口方法的调用,进而发起网络请求
invoke是ServiceMethod的抽象方法,由其直接子类HttpServiceMethod实现HttpServiceMethod.invoke(args)
1】实现了父类ServiceMethod的方法
2】创建Call对象:
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
3】在实现的invoke方法中,又转交给HttpServiceMethod.adapt的抽象方法去完成的HttpServiceMethod.adapt:
适配数据类型,并执行网络请求。
1】具体如何将Call转换为指定的返回值包装类的,最终是交给实现了HttpServiceMethod的子类去完成的。
2】如在CallAdapted中,其adapt方法是直接交由传入的CallAdapter的实现类来处理的
在使用的例子中是RxJava3CallAdapterFactory内的具体实现RxJava3CallAdapter
3、“处理器”工厂:
这里我将类型适配器CallAdapter和解析转换器Converter称之为处理器,两者都用了 抽象工厂模式。
CallAdapter:是对响应的数据进行转换,由T类型转换为R类型,这里用了 适配器模式
Converter:是对请求数据和响应结果进行处理的数据类型转换的处理类。
-
CallAdapter
1】Retrofit中定义了接口CallAdapter<R, T>,并由具体的子类实现如下方法:
①Type responseType();:返回具体的内部类型,如UserBean
②T adapt(Call<R> call);:用于将retrofit2.Call转换为 返回值包装类,如Observable,并执行请求
2】Retrofit默认只支持retrofit2.Call作为接口方法的 返回值包装类,
可通过实现CallAdapter接口进行扩展Call,适配器的添加是通过在初始化Retrofit时配置的:
Retrofit.Builder.addCallAdapterFactory方法,可加多个适配器来转换 返回值包装类,
如可设置RxJava2CallAdapterFactory的Adapter
3】而真正使用的只有一个,在Retrofit#nextCallAdapter中处理了相关逻辑
根据类型和注解的相关信息,循环List<CallAdapter.Factory>进行匹配,
根据returnType(Type)、annotations(Annotation[])等信息,匹配到了适配器(即返回结果不为null),则终止循环,直接返回这个factory。public interface CallAdapter<R, T> { Type responseType(); T adapt(Call<R> call); } -
Converter
1】Retrofit中定义了接口Converter<F, T>,并由具体的子类实现convert方法:
①T convert(F value):即从F到T(数据Bean)之间的转换操作。(多是处理POST请求)
F一般是RequestBody(请求体)或是ResponseBody(响应体),而T是通过convert方法返回的转换类型(如UserBean)。
2】Retrofit提供了addConverterFactory方法,来配置添加转换实体的工厂对象,可加多个
① 在请求的时候,通过Retrofit#requestBodyConverter方法(在构建RequestFactory中调用的)获取指定的 请求 数据解析器。
② 通过Retrofit#responseBodyConverter方法(在HttpServiceMethod#createResponseConverter中获得的)获取指定的 响应 数据解析器。
3】在HttpServiceMethod#parseAnnotations方法中调用了HttpServiceMethod#createResponseConverter,
并在其内部获取到匹配的转换器,实际调用了Retrofit#responseBodyConverter方法
4】在获取响应结果的转换器Retrofit#responseBodyConverter(实际调用了nextResponseBodyConverter方法)中,会循环遍历converterFactories转换器集合(addConverterFactory方法添加)
直到根据type(Type)、annotations(Annotation[])等信息,匹配到转换器(即返回结果不为null),则终止循环,直接返回这个factory。public interface Converter<F, T> { T convert(F value) throws IOException; }
4、请求的发起OkHttpCall
Retrofit 中真正发起网络请求的,最终还是通过的OkHttp,所以要创建OkHttpCall
-
OkHttpCall对象的创建:
在HttpServiceMethod.invoke(args)的方法中,创建了OkHttpCall对象
并将其实例传给了抽象方法adapt,是由子类决定如何通过OkHttp的实例发起网络请求@Override final @Nullable ReturnT invoke(Object[] args) { Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); return adapt(call, args); } -
OkHttpCall#getRawCall -> createRawCall
在方法中,创建了真正的请求调用对象,并传入了请求的相关信息
返回的Call实例,是OkHttp中的请求对象,所以具体的请求还是由OkHttp完成的。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; } OkHttpCall#enqueue / execute方法:
1】OkHttpCall类中是具体发起请求的地方,即重写的enqueue / execute方法
2】在接口(GitHubService)中定义的方法(listRepos)的返回类型Call<ResponseBody>,这里的Call实际上就是OkHttpCall类型
3】当调用call.enqueue(Callback)时,enqueue就是OkHttpCall中的具体实现,而Callback(retrofit2.Callback)会在okhttp3.Callback回调时进行转换。
4】HttpServiceMethod的子类实现的adapt方法中,根据传入的Call,又调用了其enqueue来执行请求的异步任务。
5、结果返回类型
例子中的Call<List<Repo>> 是如何返回的呢?
-
类型说明
首先先明确一下,Retrofit中如何对这个返回类型中的各个部分定义的:- returnType:接口方法中的 返回值类型,如
Call<List<Repo>> - rawType:接口方法中的 返回值包装类,如
Call - responseType:接口方法中返回的数据Bean类型,如
List<Repo>
- returnType:接口方法中的 返回值类型,如
-
创建对象后的类型返回
1】ReturnT invoke:
上面1中说到,请求的方法通过invoke方法来调用的,那返回类型就从这里入手,
而invoke是在ServiceMethod中定义的,具体实现在HttpServiceMethod的invoke中(之前ServiceMethod无实现类的时候,代码直接写在Retrofit中来实现的),
而HttpServiceMethod#invoke中又包了一层了adapt抽象方法,adapt定义的返回值的类型ReturnT就是接口方法的返回类型(如Call<List<Repo>>)@Override final @Nullable ReturnT invoke(Object[] args) { Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); return adapt(call, args); } protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);2】
ReturnT adapt(Call<ResponseT> call, Object[] args)
adapt方法的具体实现类是CallAdapted<ResponseT, ReturnT>(非kotlin协程),就在HttpServiceMethod中,是个内部类。此方法是通过CallAdapter来实现的,它其中的adapt方法就是一个类型转换器,具体后面介绍。@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) { return callAdapter.adapt(call); }3】
CallAdapter的具体实现有很多,其中有个最原始的支持:DefaultCallAdapterFactory,
此类中直接创建的匿名内部类CallAdapter的实现没有具体转换,只转成了最基本的Call类型,是因为要将线程中的请求结果,发送到主线程中,这其中就将Handler的消息发送包装了起来: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中,对相关的泛型参数类型进行了处理:@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);1】先判断
rawType为Call,在DefaultCallAdapterFactory的只对Call类型处理
2】然后判断其中是否有泛型参数(即returnType[如Call<List<Repo>>] 是否是参数化类型ParameterizedType)
3】再从参数化类型中取出泛型实参(responseType[如List<Repo>]),这里取的上限(Call<? extends Foo>)的第一个(有可能有多个泛型实参)。 如何处理非原始支持的类型,如kotlin的
Deffered:
同样的,也是需要实现CallAdapter来具体的进行转换返回相应的类型。
6、如何获取返回结果的泛型实参
问题:java泛型有类型擦除,那是如何在运行时获得XxxBean(如List<Repo>)的呢?
上面说到,在获取returnType 之后,判断是否为泛型参数类型(ParameterizedType),
然后再通过CallAdapter中的getParameterUpperBound (取类型的上限)
//Factory中
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
//Utils中
static Type getParameterUpperBound(int index, ParameterizedType type) {
//types即为<Xxx, Yyy, ...> 中的 Xxx, Yyy, ...这一数组
//获取泛型实参,主要在这里:getActualTypeArguments
Type[] types = type.getActualTypeArguments();
if (index < 0 || index >= types.length) {
throw new IllegalArgumentException(
"Index " + index + " not in range [0," + types.length + ") for " + type);
}
Type paramType = types[index];
//对通配符的判断
if (paramType instanceof WildcardType) {
return ((WildcardType) paramType).getUpperBounds()[0];
}
return paramType;
}
如果需要获取泛型类型,就要在混淆的时候,保留相关的方法处理,不能进行混淆。
若混淆了,生成的如下面的字节码上的注释都会被干掉,因此这些泛型类型都会被去掉,就无法获取到了。
- 原始代码:
public static Map<List<String>, Set<Map<Number, String>>> test(Map<String, Set<Map<Number, String>>> map) { return null; } - 编译后的字节码:
// access flags 0x9 // signature (Ljava/util/Map<Ljava/lang/String;Ljava/util/Set<Ljava/util/Map<Ljava/lang/Number;Ljava/lang/String;>;>;>;)Ljava/util/Map<Ljava/util/List<Ljava/lang/String;>;Ljava/util/Set<Ljava/util/Map<Ljava/lang/Number;Ljava/lang/String;>;>;>; // declaration: java.util.Map<java.util.List<java.lang.String>, java.util.Set<java.util.Map<java.lang.Number, java.lang.String>>> test(java.util.Map<java.lang.String, java.util.Set<java.util.Map<java.lang.Number, java.lang.String>>>) public static test(Ljava/util/Map;)Ljava/util/Map;
泛型擦除是一个无奈之举,因为在java1.5出现泛型之前的1.4版本及之前的版本,已经使用的很广泛了,为了兼容之前的代码程序。
C#是将泛型作为一个真实的类型存在,没有泛型擦除的问题。
7、Retrofit中的kotlin协程
- 使用:可直接返回实体Bean,而不需要任何包装类
interface GitHubService {
@GET("getUserData")
suspend fun getUserData(): UserBean
}
data class UserBean(val userName: String, val userAge: Long)
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(GitHubService::class.java)
val job: Job = launch {
try {
val userBean: UserBean = service.getUserData()
println("userBean: $userBean")
} catch (e: Throwable) {
println("onFailure: $e")
}
}
-
内部解析
1】Retrofit是以Java语言实现的,而suspend挂起函数只能用于ktolin,不过都会编译为JVM语言
通过将接口ApiService反编译得到的Java类,结果如下:public interface ApiService { @GET("getUserData") @Nullable Object getUserData1(@NotNull Continuation var1); }2】在
RequestFactory中包含一个isKotlinSuspendFunction的成员,用来标记当前解析的Method是否为suspend函数。
而isKotlinSuspendFunction的值,是在RequestFactory#build方法中跟进方法参数的最后一个是否为Continuation.class来判定的。3】在处理方法的解析中,
HttpServiceMethod#parseAnnotations内,根据isKotlinSuspendFunction来处理kotlin协程的接口方法的解析结果
如果是,则返回SuspendForResponse(得到Response对象)或SuspendForBody(得到数据Bean对象,如UserBean)对象,皆为HttpServiceMethod的子类4】
SuspendForBody实现的adapt方法中,
将接口方法(getUserData)最后一个参数强转为Continuation<ResponseT>
最终会调用KotlinExtensions.await这个kotlin扩展方法5】
KotlinExtensions.await方法中,
以suspendCancellableCoroutine支持cancel的CoroutineScope为作用域,依旧以Call.enqueue发起OkHttp请求,得到responseBody后将其回调出去。
8、Retrofit在Android中的支持
支持主要在两方面:
① 是否支持Java8,根据Android上是否启用Java 8来判断,(Gradle中配置)
② 实现UI线程回调的Executor,将回调结果切到UI线程
- 是否为Android平台的判断:
根据虚拟机的名称来判断,其中定义的Android类,是Platform的唯一子类
private static Platform findPlatform() {
//根据 JVM 名字来判断使用方是否是 Android 平台
return "Dalvik".equals(System.getProperty("java.vm.name"))
? new Android()
: new Platform(true);
}
- 是否支持
Java 8:
通过Platform中的hasJava8Types成员来判断,在Platform#Android类中,是通过构造方法传入的条件判断的:
Android() {
super(Build.VERSION.SDK_INT >= 24);
}
-
UI线程的回调实现:
1】在Platform#Android中,重写了defaultCallbackExecutor方法,
返回了创建的MainThreadExecutor对象,其中通过Handler实现了将执行任务Runnable转发到UI线程的逻辑static final class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { handler.post(r); } }2】上面说到的
CallAdapter.Factory,是用于处理接口返回值包装类(如Observable)的适配器,在Retrofit#build的时候,会将DefaultCallAdapterFactory添加进去。而DefaultCallAdapterFactory中就是处理对应的线程切换的操作。3】
DefaultCallAdapterFactory#get方法返回的CallAdapter对象,就是包装了ExecutorCallbackCall(实现了Call接口)对象,即具体实现了执行请求的ExecutorCallbackCall#enqueue方法,在此方法中,进行了任务的执行:@Override public void enqueue(final Callback<T> callback) { Objects.requireNonNull(callback, "callback == null"); delegate.enqueue( new Callback<T>() { @Override public void onResponse(Call<T> call, final Response<T> response) { callbackExecutor.execute( () -> { 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(() -> callback.onFailure(ExecutorCallbackCall.this, t)); } }); }
9、如何支持RxJava
-
在构建
Retrofit时,通过添加CallAdapterFactory:retrofit = new Retrofit.Builder() .client(OKHttpFactory.INSTANCE.getOkHttpClient()) .baseUrl(AppConfig.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) //看这里 .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); RxJava2CallAdapterFactory内部实现:
RxJava2CallAdapterFactory中对返回值类型进行一系列操作,处理泛型参数等,并处理返回
其中的returnType就是Observable<XxxBean>(XxxBean就是自己定义的需要解析的类型),拿到returnType之后,获取rawType并进行一系列判断,判断各种RxJava中定义的类型,最终将Obervable的这种rawType类型进行处理,然后在对泛型参数类型(即Observable尖括号中的泛型类型)进行获取并处理,最终进行相关赋值,并返回CallAdapter<?>-
还支持
Observable<Response<XxxBean>>
请求的时候,具体实现为BodyObservable的类型返回,真正实现adapt的相关工作Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType); Class<?> rawObservableType = getRawType(observableType); if (rawObservableType == Response.class) { if (!(observableType instanceof ParameterizedType)) { throw new IllegalStateException( "Response must be parameterized" + " as Response<Foo> or Response<? extends Foo>"); } responseType = getParameterUpperBound(0, (ParameterizedType) observableType); } else if (rawObservableType == Result.class) { if (!(observableType instanceof ParameterizedType)) { throw new IllegalStateException( "Result must be parameterized" + " as Result<Foo> or Result<? extends Foo>"); } responseType = getParameterUpperBound(0, (ParameterizedType) observableType); isResult = true; } else { responseType = observableType; isBody = true; } return new RxJava2CallAdapter( responseType, scheduler, isAsync, isResult, isBody, isFlowable, isSingle, isMaybe, false); }
10、如何在反序列化时实例化对象
具体处理类是GsonConverterFactory
其中在处理request请求和response响应时,通过 gson.getAdapter 来返回TypeAdapter ,并传入 GsonRequestBodyConverter 或 GsonResponseBodyConverter 构造来处理解析的数据。在 TypeAdapterFactory 获取的TypeAdapter 实现的,一般是ReflectiveTypeAdapterFactory ,而ObjectTypeAdapter 中的read 方法是对基本数据类型进行处理解析。
具体的实例化是,在 Gson 构造函数中,创建了一个ConstructorConstructor 构造器的构造器,接收一个instanceCreators(调用者传进来的):
Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy, final Map<Type,
InstanceCreator<?>> instanceCreators,
..., ...//省略好多入参....
) {
//省略好多....
this.constructorConstructor = new ConstructorConstructor(instanceCreators);
//省略好多....
}
在ConstructorConstructor 中对对象的构造做了很多流程判断(如图),判断了是否有无参构造(通过newDefaultConstructor)
终极方案就是使用newUnsafeAllocator 中的native 方法来开辟对象内存空间:
public native Object allocateInstance(Class<?> var1) throws InstantiationException;
在终极方案中,进行实例化对象:
private <T> ObjectConstructor<T> newUnsafeAllocator(
final Type type, final Class<? super T> rawType) {
return new ObjectConstructor<T>() {
private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
@SuppressWarnings("unchecked")
@Override public T construct() {
try {
//看这里
Object newInstance = unsafeAllocator.newInstance(rawType);
return (T) newInstance;
} catch (Exception e) {
throw new RuntimeException(("Unable to invoke no-args constructor for " + type + ". "
+ "Registering an InstanceCreator with Gson for this type may fix this problem."), e);
}
}
};
}
最终实例化了对象,实例化的时机,是在read的时候:
//ReflectiveTypeAdapterFactory <-- 大多数都是这个factory
public static final class Adapter<T> extends TypeAdapter<T> {
private final ObjectConstructor<T> constructor;
private final Map<String, BoundField> boundFields;
Adapter(ObjectConstructor<T> constructor, Map<String, BoundField> boundFields) {
this.constructor = constructor;
this.boundFields = boundFields;
}
@Override
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
//看这里啊,这里啥都木有,就是实例化一个对象,字段全是默认值
T instance = constructor.construct();
//省略好多.....
return instance;
}
@Override
public void write(JsonWriter out, T value) throws IOException {
//省略好多.....
}
}

设计模式举例:
1、Builder模式

2、工厂模式
- 抽象工厂模式:生产一系列的产品,关注的是一个大的集合
- 工厂方法模式:创建一类对象,一种产品
- 二者关联:抽象工厂通常是工厂方法来实现的



-
简单工厂:根据传递的参数(String、class等等)来创建对应的类对象(产品)
特点:接口较少,简单方便
缺点:增加产品的时候,需要增加/修改simpleFactory的代码
简单工厂
3、适配器模式

-
adapt接收一种类型(接口),让实现者去转换为具体的结果,接收的是R类型,返回的是T类型。
除了Retrofit的CallAdapter,还有Gson中的TypeAdapter同样也是适配器模式

4、代理模式

访问子类(真正实现类)不可直接访问,要通过Proxy 的访问策略,来对内部私有的子类成员来进行控制访问。都实现了同样的接口(父类Subject)
需要注意的是,在Retrofit中创建实例的时候,虽然用了java中的动态代理,但并不是严格意义上的代理?难道不是代理了传入的接口service 么?
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() {
//省略好多...
}
- 代理模式 vs 装饰模式
- 代理模式:控制访问
- 装饰模式:增强功能
如何分析源码总结:
- 带着问题入手
- 从最熟悉的部分切入
- 看看有哪些可扩展性设计
- 分析下运用了哪些设计模式
