根据这张思维导图,我们开始这篇文章的学习
Retrofit主要是对Android网络请求的框架的封装,它遵循Restful设计风格,底层基于OkHttp。
换句说,网络请求的工作本质上是OkHttp完成,而Retrofit仅负责网络请求接口的封装。
主要是使用Retrofit接口封装请求参数、header头部、Url信息等,然后交给OkHttp完成后续的网络请求,当服务端返回数据时,OkHttp又将返回的原始数据交给Retrofit,Retrofit再根据需求解析数据
简单明了的讲,Retrofit主要是对信息的封装
public interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
这里举的例子使用的网络请求方法是:@GET,使用的网络请求参数是:@Path
网络请求方法:
网络请求标记:
网络请求参数:
https://square.github.io/retrofit/
这里有解释上面这些注解都是怎么用的
//创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()//获取到一个平台和builder对象
.baseUrl("xxxxxx")//xxxxxx 代表 网络请求的公共Url地址
.addConverterFactory(GsonConverterFactory.create())//设置数据解析器
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())//支持RXJava
.build();
//这里采用的是Java的动态代理模式,创建接口对象
GitHub github = retrofit.create(GitHub.class);//这里 GitHub.class 是你自己建的接口
//对 发送请求 进行封装,配置网络请求参数
//Contributor 是你自己建的Bean,用于解析返回的数据,contributors 方法是你在接口中自己定义的方法,传入适当的参数
Call> call = github.contributors(参数1,参数2);
//采用异步请求
call.enqueue(new Callback>() {
public void onResponse(Call> call, Response> response) {
//请求成功,处理返回的数据结果
}
public void onFailure(Call> call, Throwable t) {
//请求失败,处理失败后的逻辑
}
});
//采用同步请求
Response response = call.execute();
上面是Retrofit的实现步骤,并且在代码中配备了清楚的注释
由于是从github上下的Retrofit的源码分析的,所以可能跟前辈们出的分析文章有些许的差异,但是大体上都是差不多的,这里用的版本是 :com.squareup.retrofit2:retrofit:2.5.0
看完Retrofit的使用,该来看重头戏了,Retrofit的源码分析
我们来看Retrofit实例是怎么创建的,先来看源码的追踪过程:
//配置网络请求配置对象的,,配置对象:会对网络请求接口中的方法和注解进行解析,解析之后的对象会放在ConcurrentHashMap里面,
// 作用是用于存储网络请求相关的一些配置,即跟网络请求相关的配置都存储在这个hashMap中,包括网络请求的一些方法,数据转换器,网络请求适配器,网络请求工厂和URL地址等
private final Map> serviceMethodCache = new ConcurrentHashMap<>();
//callFactory 是网络请求器的工厂,用于去生产Call请求对象,call请求就是网络请求器,无论是同步还是异步请求都是通过call调用的,并且可以看到默认的请求方式是OkHttp
final okhttp3.Call.Factory callFactory;
//网络请求的URL 地址,使用的 HttpUrl 类型
final HttpUrl baseUrl;
//数据转化器工厂的集合,作用是用于放置数据转换器工厂,而数据转换器工厂就是用于生产数据转化器 Converter 的,
// 这里最使用的就是GsonConverterFactory ,服务器返回json 类型的数据,通过Gson解析器进行解析,并在主线程中去显示
final List converterFactories;
//网络请求适配的工厂集合,作用是用于放置网络请求适配器的工厂,而网络请求适配的工厂就是用于生产网络请求适配器的
final List callAdapterFactories;
//回调方法执行器,主要是用于 主线程切换到子线程,子线程切换到主线程
final @Nullable Executor callbackExecutor;
//标志位,判断是否提前对接口中的注解进行转换的标志位
final boolean validateEagerly;
以上就是Retrofit中的成员变量,我在上面都进行了相应的注释
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
/**
* 获取对应的平台,判断是java还是android
*
* @return
*/
private static Platform findPlatform() {
try {
//通过反射装载android.os.Build类,获取SDK的版本信息
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();
}
static class Android extends Platform {
@IgnoreJRERequirement // Guarded by API check.
@Override boolean isDefaultMethod(Method method) {
if (Build.VERSION.SDK_INT < 24) {
return false;
}
return method.isDefault();
}
//创建了一个名为MainThreadExecutor的对象
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
//使用默认CallAdapter工厂生成一个执行器
@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.emptyList();
}
@Override int defaultConverterFactoriesSize() {
return Build.VERSION.SDK_INT >= 24 ? 1 : 0;
}
//MainThreadExecutor行线程切换的执行器
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
//Retrofit获取主线程的handler,通过post将子线程切换至主线程
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
//将baseUrl转换为Okhttp中的HttpUrl
return baseUrl(HttpUrl.get(baseUrl));
}
Retrofit内部会通过动态代理模式将接口和注解转换成HTTP请求
动态代理模式,动态的去生成网络请求接口代理类,交给InvocationHandler代理类处理
动态创建网络请求的接口的实例,在接口中定义网络请求的参数和方法,通过动态代理来拦截接口中定义好的注解,参数和方法
创建ServiceMethod对象,通过建造这模式和单例模式
对ServiceMethod对象进行网络请求参数配置,通过解析网络请求接口方法的参数的返回值、注解类型,获取url地址、线程切换的执行器、数据转换器、网络请求适配器
对ServiceMethod对象加入线程切换的操作,便于接收到数据后完成子线程到主线程的切换,然后交给主线程进行最后的数据处理
最终创建并返回一个OkHttpCall类型的网络请求对象,有了OkHttpCall对象和Request对象就可以进行网络的请求了
对网络请求接口的方法中的每个参数利用对应ParameterHandler进行解析,根据ServiceMethod对象创建一个OkHttp所使用的Request对象
使用OkHttp的Request结合OkHttpCall对象发送网络请求
对返回的数据使用之前设置的数据转换器(GsonConverterFactory)解析服务器返回的数据,得到一个Response对象
进行线程切换从而在主线程处理返回的数据结果