1. Retrofit简介

Retrofit是Square公司的又一力作,针对Android网络请求的框架,遵循Restful设计风格,底层基于OkHttp

他对比其他框架

  • 性能最好
  • 封装程度高,拓展性差
  • 简介易用,代码简单
  • 解耦彻底
  • 可以非常方便的与RxJava连用

2. Retrofit用法(异步)

2.1 添加依赖

可以在Retrofit Github库页面里面找到最新版本号,我写这篇博客时最新版导入方式

在你项目的app的build.gradle里面添加
implementation 'com.squareup.retrofit2:retrofit:2.6.1'

同时,如果你需要配套的数据转换器还需要导入以下的依赖

  • Gson: com.squareup.retrofit2:converter-gson
  • Jackson: com.squareup.retrofit2:converter-jackson
  • Moshi: com.squareup.retrofit2:converter-moshi
  • Protobuf: com.squareup.retrofit2:converter-protobuf
  • Wire: com.squareup.retrofit2:converter-wire
  • Simple XML: com.squareup.retrofit2:converter-simplexml
  • Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

2.2 添加网络权限

在你APP的AndroidManifest.xml里添加
<uses-permission android:name="android.permission.INTERNET"/>

2.3 创建 接收服务器返回数据 的类

Reception.java

1
2
3
4
puublic class Reception {
// 根据返回数据的格式和数据解析方式定义
...
}

2.4 创建 用于描述网络请求 的接口

GetRequest_Interface.interface

1
2
3
4
5
6
7
8
9
public interface GetRequest_Interface {
@GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
Call<Translation> getCall();
// @GET注解的作用:采用Get方法发送网络请求

// getCall() = 接收网络请求数据的方法
// 其中返回类型为Call<*>,*是接收数据的类(即上面定义的Translation类)
// 如果想直接获得Responsebody中的内容,可以定义网络请求返回值为Call<ResponseBody>
}

2.5 创建Retrofit实例

1
2
3
4
5
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://fanyi.youdao.com/") // 设置网络请求的Url地址
.addConverterFactory(GsonConverterFactory.create()) // 设置数据解析器
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava平台
.build();

2.6 创建网络请求接口实例

1
2
3
4
5
// 创建 网络请求接口 的实例
GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);

//对 发送请求 进行封装
Call<Reception> call = request.getCall();

2.7 发送网络请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//发送网络请求(异步)
call.enqueue(new Callback<Translation>() {
//请求成功时回调
@Override
public void onResponse(Call<Translation> call, Response<Translation> response) {
//请求处理,输出结果
response.body().show();
}

//请求失败时候的回调
@Override
public void onFailure(Call<Translation> call, Throwable throwable) {
System.out.println("连接失败");
}
});

2.8 处理返回数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//发送网络请求(异步)
call.enqueue(new Callback<Translation>() {
//请求成功时回调
@Override
public void onResponse(Call<Translation> call, Response<Translation> response) {
// 对返回数据进行处理
response.body().show();
}

//请求失败时候的回调
@Override
public void onFailure(Call<Translation> call, Throwable throwable) {
System.out.println("连接失败");
}
});

由于本文的核心不是讲用法,所以关于用法这块,我并没有多讲,大家若想多了解,可以看此博客:这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)

3. Retrofit源码

3.1 Retrofit对象构造源码

应对一个框架的源码首先从使用它的地方开始,我们先来看Retrofit的创建代码:

1
2
3
4
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://fanyi.youdao.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();

我们可以把它分为5个部分来分析源码:
源码分析步骤

我们首先来看第一步

3.1.1 步骤1:Retrofit类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public final class Retrofit {
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();

// 网络请求工厂
final okhttp3.Call.Factory callFactory;
// 请求的Url地址
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;
}
...// 省略后面的代码
}

可以看到,Retrofit的构造方法需要一次性把需要的数据全部准备好。
而且这块有特别多的工厂,使用了工厂模式。这个我们之后再讲,接下来看步骤2:

3.1.2 步骤2:Builder()方法

我们先来看下Builder()方法的源码:

1
2
3
public Builder() {
this(Platform.get());
}

这里调用了Rlatform.get()方法:

1
2
3
static Platform get() {
return PLATFORM;
}

PLATFORM的定义就在上面:

1
private static final Platform PLATFORM = findPlatform();

我们再来看下findPlatform()方法:

1
2
3
4
5
6
7
8
9
10
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
return new Platform(true);
}

这块创建了一个Android对象,接着返回了传入true创建的Platform对象。我们再来看下Android类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static final class Android extends Platform {
Android() {
super(Build.VERSION.SDK_INT >= 24);
}

@Override public Executor defaultCallbackExecutor() {
// 返回一个默认的回调方法执行器
// 该执行器作用:切换线程(子->>主线程),并在主线程(UI线程)中执行回调方法
return new MainThreadExecutor();
}

static class MainThreadExecutor implements Executor {
// 获取与Android 主线程绑定的Handler
private final Handler handler = new Handler(Looper.getMainLooper());

@Override public void execute(Runnable r) {
// 该Handler是上面获取的与Android 主线程绑定的Handler
// 在UI线程进行对网络请求返回数据处理等操作。
handler.post(r);
}
}
}

3.1.3 步骤3:baseUrl()方法

1
2
3
4
public Builder baseUrl(String baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl));
}

最后还是调用了一个baseUrl()方法,我们来看看这个baseUrl()方法:

1
2
3
4
5
6
7
8
9
10
11
public Builder baseUrl(HttpUrl baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
// 把URL参数分割成几个路径碎片
List<String> pathSegments = baseUrl.pathSegments();
// 检测最后一个碎片来检查URL参数是不是以"/"结尾,不是就抛出异常
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}

步骤3用于设置网络请求的Url

3.1.4 步骤4:addConverterFactory()方法

我们先来看看GsonConverterFactory.create()方法:

1
2
3
public static GsonConverterFactory create() {
return create(new Gson());
}

又调用了另一个create()方法:

1
2
3
4
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}

如果传入的gson为空就报异常,不为空就调用GsonConverterFactory的构造方法:

1
2
3
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}

所以这个方法本质就是返回了一个gson对象给了addConverterFactory()方法,那我们再来看看这个方法:

1
2
3
4
5
/** 为对象的序列化和反序列化添加转换器工厂。 */
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
return this;
}

步骤4创建了一个含有Gson实例的GsonConverterFactory对象,并放入了ConverterFactory

3.1.5 步骤5:build()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
// 配置网络请求执行器
okhttp3.Call.Factory callFactory = this.callFactory;
// 如果没有指定callFactory,则创建OkHttpClient
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// 配置回调执行器
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}

// 配置网络请求适配器工厂
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());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());

return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}

按前面配置的变量,将Retrofit所有的变量都配置好,最后完成创建Retrofit实例。

到这Retrofit的创建部分就完了。
Retrofit通过建造者模式创建了一个Retrofit实例:

  • 请求工厂callFactory:默认是OkHttpClient
  • 数据转换器工厂converterFactories
  • 网络请求适配器工厂callAdapterFactories:默认是ExecutorCallAdapterFactory
  • 回调执行器callbackExecutor

Retrofit对象构建流程

3.2 创建网络请求接口的实例

大致创建方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- Reception.java -->
puublic class Reception {
// 根据返回数据的格式和数据解析方式定义
...
}

<!-- GetRequest_Interface.interface -->
public interface GetRequest_Interface {
@GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
Call<Translation> getCall();
// @GET注解的作用:采用Get方法发送网络请求

// getCall() = 接收网络请求数据的方法
// 其中返回类型为Call<*>,*是接收数据的类(即上面定义的Translation类)
// 如果想直接获得Responsebody中的内容,可以定义网络请求返回值为Call<ResponseBody>
}

<!-- MainActivity.java -->
// 创建 网络请求接口 的实例
GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
//对 发送请求 进行封装
Call<Reception> call = request.getCall();

我们先看看retrofit.create()干了啥:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 (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);
}
});
}

首先调用了validateServiceInterface()这个方法,我们来看看这个方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
private void validateServiceInterface(Class<?> service) {
// 如果不是接口就抛异常
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}

// 构造了一个容量下限为1的空双向队列来存储数据
Deque<Class<?>> check = new ArrayDeque<>(1);
// 添加到队列
check.add(service);
while (!check.isEmpty()) {
// 将队列的正向第一个元素移除
Class<?> candidate = check.removeFirst();
// getTypeParameters()的作用是得到泛型类型,如果泛型的数量不为0的话进入
if (candidate.getTypeParameters().length != 0) {
StringBuilder message = new StringBuilder("Type parameters are unsupported on ")
.append(candidate.getName());
if (candidate != service) {
message.append(" which is an interface of ")
.append(service.getName());
}
throw new IllegalArgumentException(message.toString());
}
Collections.addAll(check, candidate.getInterfaces());
}

if (validateEagerly) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
}

获取到Platform(平台),然后再遍历接口中的方法,调用loadServiceMethod()方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}

这个方法主要就是通过serviceMethodCache来存储转换为ServiceMethod类型的Method

那我们在回过去看InvocationHandlerinvoke()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 (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);
}
});

两个if先不管,先看最后的return,可以看到他调用了一个loadServiceMethod()方法,而这个方法在前面就说过,主要就返回了一个ServiceMethod。那我们接着来看invoke()方法:
按住command+鼠标左键进入后,显示的是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
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);
}

abstract @Nullable T invoke(Object[] args);
}

这个invoke()根本就是个抽象方法啊,然后我又回去找看看有没有说是哪个继承自ServiceMethod的类实现了这个方法,结果也没找到,最后想到了AndroidStudio可以command+左键找实现了这个类的地方啊。于是我就点了下这个类,结果成功找到了HttpServiceMethod这个类,他是ServiceMethod的子类中唯一一个实现了invoke()方法的:
1
2
3
4
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}

可以看到这块他创建了一个OkHttpCall对象,此处不做详解,可以看我关于OkHttp的一篇博客:Android网络请求3—解析OkHttp源码。然后调用了adapt方法,我们来看看这个方法:

1
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);

这又是一个抽象方法。只不过好的是,这个方法下面我们就找到了他的实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;

CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}

@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}

可是他又返回给了一个CallAdapter接口的实现类的adapt()方法。。。。艹

所以,这块我就不懂了,我不知道他到底咋实现这个的这个方法的,我看了《Android进阶之光》和其它很多博客,他们都是老版本的Retrofitcreate()方法不同,而且调用的adapt()方法也不同。。。

Retrofit网络请求接口创建

3.3 网络请求

网络请求这块Retrofit实际上就是用OkHttp实现的,所以这块我就不在这多说了,大家要了解的可以看我之前写的博客:Android网络请求3—解析OkHttp源码