Retrofit是一个RESful的HTTp网络请求框架的封装
原因是:网络请求的工作本质上是okHttp完成的,而Retrofit仅负责网络请求接口的封装
1.上图说明了啥
1.app应用程序通过Retrofit请求网络,实际上是使用Retrofit接口层封装请求参数,Header,Url等信息,之后由OKHttp完成后续的请求操作
2.在服务器返回数据之后,oktttp将原始的结果交给Retrofit,Retrofit根据用户的需求结果进行分析
在我们看Retrofit的构建过程
Retrofit通过Build模式来生成一个Retrofit对象,通过代码我们知道,Retrofit默认会使用OkHTTP来发送网络请求,当然我们也可以自己定制
public Retrofit build() {
<-- 配置网络请求执行器(callFactory)-->
okhttp3.Call.Factory callFactory = this.callFactory;
// 如果没指定,则默认使用okhttp
// 所以Retrofit默认使用okhttp进行网络请求
if (callFactory == null) {
callFactory = new OkHttpClient();
}
<-- 配置回调方法执行器(callbackExecutor)-->
Executor callbackExecutor = this.callbackExecutor;
// 如果没指定,则默认使用Platform检测环境时的默认callbackExecutor
// 即Android默认的callbackExecutor
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
<-- 配置网络请求适配器工厂(CallAdapterFactory)-->
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
// 向该集合中添加了步骤2中创建的CallAdapter.Factory请求适配器(添加在集合器末尾)
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// 请求适配器工厂集合存储顺序:自定义1适配器工厂、自定义2适配器工厂...默认适配器工厂(ExecutorCallAdapterFactory)
<-- 配置数据转换器工厂:converterFactory -->
// 在步骤2中已经添加了内置的数据转换器BuiltInConverters()(添加到集合器的首位)
//中又插入了一个Gson的转换器 - GsonConverterFactory(添加到集合器的首二位)
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
// 数据转换器工厂集合存储的是:默认数据转换器工厂( BuiltInConverters)、自定义1数据转换器工厂(GsonConverterFactory)、自定义2数据转换器工厂....
// 注:
//1. 获取合适的网络请求适配器和数据转换器都是从adapterFactories和converterFactories集合的首位-末位开始遍历
// 因此集合中的工厂位置越靠前就拥有越高的使用权限
// 最终返回一个Retrofit的对象,并传入上述已经配置好的成员变量
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
}
// 在第二步放入一个内置的数据转换器工厂BuiltInConverters()后又放入了一个GsonConverterFactory
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
<-- 步骤3:在MainActivity创建接口类实例 -->
AccessApi NetService = retrofit.create(NetService.class);
<-- 步骤4:对发送请求的url进行封装,即生成最终的网络请求对象 -->
Call<JavaBean> call = NetService.getCall();
这是GsonConverterFactory的类的创建过程
public final class GsonConverterFactory extends Converter.Factory {
/**
* Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
public static GsonConverterFactory create() {
return create(new Gson());
}
/**
* Create an instance using {@code gson} for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
@SuppressWarnings("unchecked")
// Single-interface proxy creation guarded by parameter safety.
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(); //统一处理所有的请求方式
@Override public 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);
}
//根据方法生成一个ServiceMethod对象(内部会将生成的ServiceMethod放入到缓存中)
//如果已经生成过了,就从缓存中获取
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//根据ServiceMethod对象和请求参数生成一个OkHttpCall对象,这个okHttpCall能够
//调用okHttp的接口发起网络请求
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
// 调用serviceMethod的callAdapter的adapt方法,并传入okHttpCall,返回一个对象,
//这个的目的主要是为了适配返回类型,其内部会对OkhttpCall对象进行包装
return serviceMethod.adapt(okHttpCall);
}
});
}
(1).Retrofit的create方法通过动态代理的模式,生成了实现了具体的网络请求接口的对象,并在InvocationHandler
的invoke方法中统一处理网络请求接口实体对象的方法;
(2).invoke方法会通过方法构造一个ServiceMethod对象,
并将其放入缓存中;
(3)然后根据ServiceMethod对象和网络请求的参数args去构造一个OkHttpCall对象;
(4)最后调用serviceMethod的callAdapter的adapt方法,传入将OkHttpCall对象,callAdapter的目的主要是为了适配
OkHttpCall对象,其内部会对OkHttpCall对象进行包装,生成对应返回类型的对象。
// Upper and lower characters, digits, underscores, and hyphens, starting with a character.
static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
//网络请求工厂 就是okHttp的网络请求
private final okhttp3.Call.Factory callFactory;
//网络请求适配器 把call请求适配各个平台
private final CallAdapter<R, T> callAdapter;
//网络基地址
private final HttpUrl baseUrl;
//数据转换器
private final Converter<ResponseBody, R> responseConverter;
//网络请求的http方法 比如get post方法
private final String httpMethod;
//网络请求的相对地址 和baseUrl拼接起来就是实际地址
private final String relativeUrl;
//请求头
private final Headers headers;
//网络请求的http报文的type
private final MediaType contentType;
//三个标志位
private final boolean hasBody;
private final boolean isFormEncoded;
private final boolean isMultipart;
//方法参数的处理器 比如我们定义的方法 上面的@get和后面的参数
private final ParameterHandler<?>[] parameterHandlers;
//可以看出是传递的是一个Builder内部类 所以ServiceMethod也是通过构建者模式来初始化他的成员变量的
ServiceMethod(Builder<R, T> builder) {
this.callFactory = builder.retrofit.callFactory();
this.callAdapter = builder.callAdapter;
this.baseUrl = builder.retrofit.baseUrl();
this.responseConverter = builder.responseConverter;
this.httpMethod = builder.httpMethod;
this.relativeUrl = builder.relativeUrl;
this.headers = builder.headers;
this.contentType = builder.contentType;
this.hasBody = builder.hasBody;
this.isFormEncoded = builder.isFormEncoded;
this.isMultipart = builder.isMultipart;
this.parameterHandlers = builder.parameterHandlers;
}
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method; //网络请求方法
//获取网络请求方法中的注解 @GET @POST
this.methodAnnotations = method.getAnnotations();
//获取网络请求方法中的参数类型
this.parameterTypes = method.getGenericParameterTypes();
//获取网络请求中的注解内容
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
通过Builder方法就能配置我们serviceMethod方法的成员变量
public ServiceMethod build() {
//创建callAdapter
callAdapter = createCallAdapter();
// 根据网络请求接口返回值类型和注解类型从retrofit对象当中获取这个网络适配器返回的数据类型
responseType = callAdapter.responseType();
//异常(检查代码)
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
//设置请求的数据适配器converter
responseConverter = createResponseConverter();
// 解读方法的注解
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError("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; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
Type parameterType = parameterTypes[p];
//然后通过parseParameter()这个方法来解析参数 通过我们传入的参数类型和参数的注解内容
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
return new ServiceMethod<>(this);
}
所以总结的来说就是build方法就是根据我们定义好的请求接口中的返回值类型和方法中的注解来从
我们的网络请求适配器工厂和数据转换器工厂集合中分别获取到我们所需要的网络请求适配器和response数据转换器,
然后根据参数注解去获取到我们所需要的解析的参数,最后调用parseParameter()方法来解析我们接口中的参数
//是根据retrofit网络请求中接口的方法的返回值类型和注解的类型从我们的retrofit对象当中获取对应的网络请求适配器
private CallAdapter<T, R> createCallAdapter() {
//获取网络请求接口中方法中的返回值类型
Type returnType = method.getGenericReturnType();
。。。。
//获取注解类型
Annotation[] annotations = method.getAnnotations();
//最终调用retrofit的callAdapter 返回我们的网络适配器
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
}
}
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
int start = adapterFactories.indexOf(skipPast) + 1;
//创建callAdapter 遍历这个callAdapter的工厂集合 寻找合适的工厂
for (int i = start, count = adapterFactories.size(); i < count; i++) {
//然后通过这个工厂的get方法 还有传入的返回值类型和注解类型 创建我们需要的callAdapter 比如RxJavaCallAdapterFactory
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
Retrofifit网络请求操作小结
2.利用converter进行网络请求数据的转换一般是gson
3.利用rxjava observable构建Rxjava类型的责任链访问方案,并进行线程切换
4.如果没有添加Rxjava,那么就使用默认的callAdapter里面的callbackExecutor进行线程切换,进行网络请求