「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」
前面介绍了okHttp以及常用的加密方式
这里主要讲Retrofit的用法
一、简介
Retrofit简单的总结就是通过动态代理的方式将Java接口翻译成网络请求,通过OkHttp发送请求,并且支持各种数据格式的转换
二、使用
1. 添加依赖
2. 定义接口类
public interface TranslateApi {
@POST("ajax.php?a=fy&f=auto&t=auto")
@FormUrlEncoded
Call<TranslateBean> translateRequest(@Field("w") String input);
}
3. 创建Retrofit实例
通过Builder模式构造一个Retrofit对象
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://fy.iciba.com/") // 配置HOST
// 添加解读返回数据的对象,因为返回数据是Json格式的,所以这里采用GsonConverterFactory来解读
.addConverterFactory(GsonConverterFactory.create())
// 添加适配OkHttpCall对象的CallAdapterFactory
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
4. 生成具体的请求实体对象
5. 调用Call对象的enqueue方法发起异步网络请求
6. 总结
首先我们定义了网络请求的接口,接口中配置了请求的基本信息,包括请求方法、请求参数等;接着我们生成了一个Retrofit对象,在这里可以配置请求的默认Host信息、添加解析返回数据格式的Factory、添加适配OkHttpCall的Factory等功能;然后调用retrofit对象的create方法,传入网络请求接口类,生成一个具体的网络请求实体对象;接下来我们调用了请求方法生成一个能够发起网络请求的Call对象,最后调用Call对象的enquene方法将发起异步的网络请求,并且在传入的Callback中处理网络请求的回调
二、原理分析
Retrofit核心是根据接口生成一个能够发起网络请求的对象,然后根据这个对象再发起网络请求
1. Retrofit
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
// 如果没有设置网络请求框架,模式使用OkHttp处理网络请求
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
// 默认使用platform.defaultCallbackExecutor()处理返回结果
callbackExecutor = platform.defaultCallbackExecutor();
}
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); // 根据配置信息生成一个Retrofit对象
}
Retrofit通过build模式来生成一个Retrofit对象
2. create方法根据接口生成具体的网络请求实体类
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 (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.callAdapter.adapt(okHttpCall);
}
});
}
Retrofit的create方法通过动态代理的模式,生成了实现了具体的网络请求接口的对象,并在InvocationHandler的invoke方法中统一处理网络请求接口实体对象的方法,invoke方法会通过方法构造一个ServiceMethod对象,并将其放入缓存中,然后根据ServiceMethod对象和网络请求的参数args去构造一个OkHttpCall对象,最后调用serviceMethod的callAdapter的adapt方法,传入将OkHttpCall对象,callAdapter的目的主要是为了适配OkHttpCall对象,其内部会对OkHttpCall对象进行包装,生成对应返回类型的对象
2. 动态代理
它的原理主要是在运行时动态生成代理类,然后根据代理类生成一个代理对象,在这个代理对象的方法中中又会调用InvocationHandler的invoke来转发对方法的处理
代理类的代码是动态生成的,生成代码后我们就可以用ClassLoader将其加载到内存中,并通过反射生成代理对象,代理类会将方法的处理转发给InvokeHandler,所以所有对代理对象方法的调用都会由InvocationHandler的invoke方法处理
2. ServiceMethod
ServiceMethod其实是用来存储一次网络请求的基本信息的,比如Host、URL、请求方法等,同时ServiceMethod还会存储用来适配OkHttpCall对象的CallAdpater
这篇先介绍到这里,下一篇主要分析动态代理、ServiceMethod以及出现的设计模式