Retrofit
是Android
应用层最为广泛的网络请求框架之一。
它通过动态代理、工厂模式、Builder
模式等设计模式,对Okhttp
进行了巧妙封装。
本文,将对Retrofit2
源码进行分析。若无特殊说明,源码api为2.7.2
一.动态代理
在使用Retrofit
时,我们先定义一个接口,然后通过调用retrofit.create
方法,得到一个接口的实例,最后通过该实例执行我们的操作。
Retrofit
在设计过程中,有一个很重要的知识点,动态代理.
在正式学习Retrofit
源码之前,先对Java
中的动态代理进行了解。
先定义一个接口:
代码片1
public interface ITest {
@GET("/test")
public void add(int a, int b);
}
通过动态代码的代码如下:
代码片2
ITest iTest = (ITest) Proxy.newProxyInstance(ITest.class.getClassLoader(),
new Class<?>[]{
ITest.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Integer a = (Integer) args[0];
Integer b = (Integer) args[1];
System.out.println("方法名:" + method.getName());
System.out.println("参数:" + a + " , " + b);
GET get = method.getAnnotation(GET.class);
System.out.println("注解:" + get.value());
return null;
}
});
iTest.add(3, 5);
输出结果如下:
I/System.out: 方法名:add
I/System.out: 参数:3 , 5
I/System.out: 注解:/test
可以看到通过 Proxy.newProxyInstance
产生的代理类,当调用接口的任何方法时,都会调用 Proxy#InvocationHandler
方法,在这个方法中可以拿到传入的参数、注解等。
二.Retrofit源码分析
代码片3
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create(mGson))
.build();
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> call = service.listRepos("gaolhjy");
call.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
Log.e(TAG, "onResponse: " + "success");
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
Log.e(TAG, "onResponse: " + "onFailure");
}
});
上述代码,是比较典型的使用Retrofit进行的网络请求的写法。
(一) Retrofit的创建过程
代码片4
Retrofit retrofit = new Retrofit.Builder() //1.创建builder
.baseUrl("https://api.github.com/") //2.配置builder
.build(); //3、创建Retrofit实例
1.创建builder
代码片5
public static final class Builder {
private final Platform platform; //运行Retrofit的平台
//省略部分代码
//根据Platform构造
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
//根据另外一个Retrofit构造
Builder(Retrofit retrofit) {
platform = Platform.get();
callFactory = retrofit.callFactory;
baseUrl = retrofit.baseUrl;
//省略部分代码
}
和okhttp
一样,Retrofit
的实例化也是采用builder
模式。
我们使用了无参的构造函数来创建Builder
,Builder
的无参构造函数首先通过Platform.get()
获取了一个Platform
实例赋值给了platform
字段,前面提到过Retrofit
是有Platform
的概念,Retrofit
支持java
和Android
平台。
我们来看一下Platform
类.
代码片6
class Platform {
//单例
private static final Platform PLATFORM = findPlatform();
//返回Platform 对象
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
//android.os.Build这个类是Android独有的
//这里要求JVM查找并加载Build.class对象
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
//如果是Android平台,创建一个Android实例返回,Android继承自Platform
return new Android();
}
} catch (ClassNotFoundException ignored) {
//找不到android.os.Build,会抛出异常,捕捉,继续执行
}
//返回默认Platform实例,并传hasJava8Types为true
return new Platform(true);
}
private final boolean hasJava8Types;
Platform(boolean hasJava8Types) {
this.hasJava8Types = hasJava8Types;
}
//返回默认的线程切换执行器
@Nullable Executor defaultCallbackExecutor() {
return null;
}
//返回默认的网络请求适配器工厂
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return hasJava8Types
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
int defaultCallAdapterFactoriesSize() {
return hasJava8Types ? 2 : 1;
}
List<? extends Converter.Factory> defaultConverterFactories() {
return hasJava8Types
? singletonList(OptionalConverterFactory.INSTANCE)
: emptyList();
}
int defaultConverterFactoriesSize() {
return hasJava8Types ? 1 : 0;
}
boolean isDefaultMethod(Method method) {
return hasJava8Types && method.isDefault();