网站建设要不要学编码,WordPress人物插件,网络营销策划书800字,omv wordpress文章目录一、简介二、源码分析2.1Retrofit的本质流程2.2源码分析2.2.1 创建Retrofit实例步骤1步骤2步骤3步骤4步骤5总结2.2.2创建网络请求接口的实例外观模式 代理模式1.外观模式2. 代理模式步骤3步骤4总结2.2.3执行网络请求同步请求OkHttpCall.execute()1.发送请求过程2…
文章目录一、简介二、源码分析2.1Retrofit的本质流程2.2源码分析2.2.1 创建Retrofit实例步骤1步骤2步骤3步骤4步骤5总结2.2.2创建网络请求接口的实例外观模式 代理模式1.外观模式2. 代理模式步骤3步骤4总结2.2.3执行网络请求同步请求OkHttpCall.execute()1.发送请求过程2.具体使用3.源码分析异步请求OkHttpCall.enqueue()1.发送请求过程2.具体使用3.源码分析三、总结一、简介 特别注意
准确来说Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。原因网络请求的工作本质上是 OkHttp 完成而 Retrofit 仅负责 网络请求接口的封装 App应用程序通过 Retrofit 请求网络实际上是使用 Retrofit 接口层封装请求参数、Header、Url 等信息之后由 OkHttp 完成后续的请求操作在服务端返回数据之后OkHttp 将原始的结果交给 RetrofitRetrofit根据用户的需求对结果进行解析
二、源码分析
2.1Retrofit的本质流程 具体过程解释如下
通过解析网络请求接口的注解配置网络请求参数通过 动态代理 生成网络请求对象通过 网络请求适配器 将 网络请求对象 进行平台适配 平台包括Android、Rxjava、Guava和java8 通过 网络请求执行器 发送网络请求通过 数据转换器 解析服务器返回的数据通过 回调执行器 切换线程子线程 -主线程用户在主线程处理返回结果
2.2源码分析
先来回忆Retrofit的使用步骤
创建Retrofit实例创建 网络请求接口实例 并 配置网络请求参数发送网络请求 封装了 数据转换、线程切换的操作 处理服务器返回的数据
2.2.1 创建Retrofit实例
使用步骤 Retrofit retrofit new Retrofit.Builder().baseUrl(http://fanyi.youdao.com/).addConverterFactory(GsonConverterFactory.create()).build();源码分析 Retrofit实例是使用建造者模式通过Builder类进行创建的 建造者模式将一个复杂对象的构建与表示分离使得用户在不知道对象的创建细节情况下就可以直接创建复杂的对象 接下来我将分五个步骤对创建Retrofit实例进行逐步分析
步骤1 -- Retrofit类 --public final class Retrofit {private final MapMethod, ServiceMethod serviceMethodCache new LinkedHashMap();// 网络请求配置对象对网络请求接口中方法注解进行解析后得到的对象// 作用存储网络请求相关的配置如网络请求的方法、数据转换器、网络请求适配器、网络请求工厂、基地址等private final HttpUrl baseUrl;// 网络请求的url地址private final okhttp3.Call.Factory callFactory;// 网络请求器的工厂// 作用生产网络请求器Call// Retrofit是默认使用okhttpprivate final ListCallAdapter.Factory adapterFactories;// 网络请求适配器工厂的集合// 作用放置网络请求适配器工厂// 网络请求适配器工厂作用生产网络请求适配器CallAdapter// 下面会详细说明private final ListConverter.Factory converterFactories;// 数据转换器工厂的集合// 作用放置数据转换器工厂// 数据转换器工厂作用生产数据转换器converterprivate final Executor callbackExecutor;// 回调方法执行器private final boolean validateEagerly;
// 标志位
// 作用是否提前对业务接口中的注解进行验证转换的标志位-- Retrofit类的构造函数 --
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl, ListConverter.Factory converterFactories, ListCallAdapter.Factory adapterFactories, Executor callbackExecutor, boolean validateEagerly) { this.callFactory callFactory; this.baseUrl baseUrl; this.converterFactories unmodifiableList(converterFactories); this.adapterFactories unmodifiableList(adapterFactories); // unmodifiableList(list)近似于UnmodifiableListE(list)// 作用创建的新对象能够对list数据进行访问但不可通过该对象对list集合中的元素进行修改this.callbackExecutor callbackExecutor; this.validateEagerly validateEagerly; ...// 仅贴出关键代码
}成功建立一个Retrofit对象的标准配置好Retrofit类里的成员变量即配置好
serviceMethod包含所有网络请求信息的对象baseUrl网络请求的url地址callFactory网络请求工厂adapterFactories网络请求适配器工厂的集合converterFactories数据转换器工厂的集合callbackExecutor回调方法执行器
所谓xxxFactory、“xxx工厂”其实是设计模式中工厂模式的体现将“类实例化的操作”与“使用对象的操作”分开使得使用者不用知道具体参数就可以实例化出所需要的“产品”类。
这里详细介绍一下CallAdapterFactory该Factory生产的是CallAdapter那么CallAdapter又是什么呢
CallAdapter详细介绍
定义网络请求执行器Call的适配器 Call在Retrofit里默认是OkHttpCall 在Retrofit中提供了四种CallAdapterFactory ExecutorCallAdapterFactory默认、GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory 作用将默认的网络请求执行器OkHttpCall转换成适合被不同平台来调用的网络请求执行器形式 如一开始Retrofit只打算利用OkHttpCall通过ExecutorCallbackCall切换线程但后来发现使用Rxjava更加方便不需要Handler来切换线程。想要实现Rxjava的情况那就得使用RxJavaCallAdapterFactoryCallAdapter将OkHttpCall转换成Rxjava(Scheduler) // 把response封装成rxjava的Observeble然后进行流式操作
Retrofit.Builder.addCallAdapterFactory(newRxJavaCallAdapterFactory().create());
// 关于RxJava的使用这里不作更多的展开Retrofit还支持java8、Guava平台。 好处用最小代价兼容更多平台即能适配更多的使用场景
步骤2 public static final class Builder {private Platform platform;private okhttp3.Call.Factory callFactory;private HttpUrl baseUrl;private ListConverter.Factory converterFactories new ArrayList();private ListCallAdapter.Factory adapterFactories new ArrayList();private Executor callbackExecutor;private boolean validateEagerly;// 从上面可以发现 Builder类的成员变量与Retrofit类的成员变量是对应的
// 所以Retrofit类的成员变量基本上是通过Builder类进行配置
// 开始看步骤1-- 步骤1 --
// Builder的构造方法无参public Builder() {this(Platform.get());
// 用this调用自己的有参构造方法public Builder(Platform platform) -步骤5看完步骤2、3、4再看
// 并通过调用Platform.get传入了Platform对象
// 继续看Platform.get()方法 -步骤2
// 记得最后继续看步骤5的Builder有参构造方法}
...
}-- 步骤2 --
class Platform {private static final Platform PLATFORM findPlatform();// 将findPlatform()赋给静态变量static Platform get() {return PLATFORM; // 返回静态变量PLATFORM即findPlatform() -步骤3}-- 步骤3 --
private static Platform findPlatform() {try {Class.forName(android.os.Build);// Class.forName(xxx.xx.xx)的作用要求JVM查找并加载指定的类即JVM会执行该类的静态代码段if (Build.VERSION.SDK_INT ! 0) {return new Android(); // 此处表示如果是Android平台就创建并返回一个Android对象 -步骤4}} catch (ClassNotFoundException ignored) {}try {// 支持Java平台Class.forName(java.util.Optional);return new Java8();} catch (ClassNotFoundException ignored) {}try {// 支持iOS平台Class.forName(org.robovm.apple.foundation.NSObject);return new IOS();} catch (ClassNotFoundException ignored) {}// 从上面看出Retrofit2.0支持3个平台Android平台、Java平台、IOS平台
// 最后返回一个Platform对象指定了Android平台给Builder的有参构造方法public Builder(Platform platform) -- 步骤5
// 说明Builder指定了运行平台为Androidreturn new Platform();}
...
}-- 步骤4 --
// 用于接收服务器返回数据后进行线程切换在主线程显示结果static class Android extends Platform {OverrideCallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {return new ExecutorCallAdapterFactory(callbackExecutor);// 创建默认的网络请求适配器工厂// 该默认工厂生产的 adapter 会使得Call在异步调用时在指定的 Executor 上执行回调// 在Retrofit中提供了四种CallAdapterFactory ExecutorCallAdapterFactory默认、GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory// 采用了策略模式}Override public Executor defaultCallbackExecutor() {// 返回一个默认的回调方法执行器// 该执行器作用切换线程子-主线程并在主线程UI线程中执行回调方法return new MainThreadExecutor();}static class MainThreadExecutor implements Executor {private final Handler handler new Handler(Looper.getMainLooper());// 获取与Android 主线程绑定的Handler Override public void execute(Runnable r) {handler.post(r);// 该Handler是上面获取的与Android 主线程绑定的Handler // 在UI线程进行对网络请求返回数据处理等操作。}}// 切换线程的流程
// 1. 回调ExecutorCallAdapterFactory生成了一个ExecutorCallbackCall对象
//2. 通过调用ExecutorCallbackCall.enqueue(CallBack)从而调用MainThreadExecutor的execute()通过handler切换到主线程}// 下面继续看步骤5的Builder有参构造方法
-- 步骤5 --
// Builder类的构造函数2有参public Builder(Platform platform) {// 接收Platform对象Android平台this.platform platform;// 通过传入BuiltInConverters()对象配置数据转换器工厂converterFactories// converterFactories是一个存放数据转换器Converter.Factory的数组
// 配置converterFactories即配置里面的数据转换器converterFactories.add(new BuiltInConverters());// BuiltInConverters是一个内置的数据转换器工厂继承Converter.Factory类
// new BuiltInConverters()是为了初始化数据转换器}
总结Builder设置了默认的
平台类型对象Android网络请求适配器工厂CallAdapterFactory CallAdapter用于对原始Call进行再次封装如Call到Observable 数据转换器工厂 converterFactory回调执行器callbackExecutor
特别注意这里只是设置了默认值但未真正配置到具体的Retrofit类的成员变量当中
步骤3 public Builder baseUrl(String baseUrl) {// 把String类型的url参数转化为适合OKhttp的HttpUrl类型HttpUrl httpUrl HttpUrl.parse(baseUrl); // 最终返回带httpUrl类型参数的baseUrl// 下面继续看baseUrl(httpUrl) - 步骤2return baseUrl(httpUrl);}-- 步骤2 --public Builder baseUrl(HttpUrl baseUrl) {//把URL参数分割成几个路径碎片ListString pathSegments baseUrl.pathSegments(); // 检测最后一个碎片来检查URL参数是不是以/结尾// 不是就抛出异常 if (!.equals(pathSegments.get(pathSegments.size() - 1))) {throw new IllegalArgumentException(baseUrl must end in /: baseUrl);} this.baseUrl baseUrl;return this;}
总结baseUrl用于配置Retrofit类的网络请求url地址 将传入的String类型url转化为适合OKhttp的HttpUrl类型的url 步骤4 我们从里往外看即先看GsonConverterFactory.creat()
public final class GsonConverterFactory extends Converter.Factory {-- 步骤1 --public static GsonConverterFactory create() {// 创建一个Gson对象return create(new Gson()); -步骤2}-- 步骤2 --public static GsonConverterFactory create(Gson gson) {// 创建了一个含有Gson对象实例的GsonConverterFactoryreturn new GsonConverterFactory(gson); -步骤3}private final Gson gson;-- 步骤3 --private GsonConverterFactory(Gson gson) {if (gson null) throw new NullPointerException(gson null);this.gson gson;}所以GsonConverterFactory.creat()是创建了一个含有Gson对象实例的GsonConverterFactory并返回给addConverterFactory接下来继续看addConverterFactory
// 将上面创建的GsonConverterFactory放入到 converterFactories数组
// 在第二步放入一个内置的数据转换器工厂BuiltInConverters(后又放入了一个GsonConverterFactorypublic Builder addConverterFactory(Converter.Factory factory) {converterFactories.add(checkNotNull(factory, factory null));return this;}至此分析完毕总结步骤4用于创建一个含有Gson对象实例的GsonConverterFactory并放入到数据转换器工厂converterFactories里
步骤5 -- 配置网络请求执行器callFactory--okhttp3.Call.Factory callFactory this.callFactory;// 如果没指定则默认使用okhttp// 所以Retrofit默认使用okhttp进行网络请求if (callFactory null) {callFactory new OkHttpClient();}-- 配置回调方法执行器callbackExecutor--Executor callbackExecutor this.callbackExecutor;// 如果没指定则默认使用Platform检测环境时的默认callbackExecutor// 即Android默认的callbackExecutorif (callbackExecutor null) {callbackExecutor platform.defaultCallbackExecutor();}-- 配置网络请求适配器工厂CallAdapterFactory--ListCallAdapter.Factory adapterFactories new ArrayList(this.adapterFactories);// 向该集合中添加了步骤2中创建的CallAdapter.Factory请求适配器添加在集合器末尾adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));// 请求适配器工厂集合存储顺序自定义1适配器工厂、自定义2适配器工厂...默认适配器工厂ExecutorCallAdapterFactory-- 配置数据转换器工厂converterFactory --// 在步骤2中已经添加了内置的数据转换器BuiltInConverters(添加到集合器的首位// 在步骤4中又插入了一个Gson的转换器 - GsonConverterFactory添加到集合器的首二位ListConverter.Factory converterFactories new ArrayList(this.converterFactories);// 数据转换器工厂集合存储的是默认数据转换器工厂 BuiltInConverters、自定义1数据转换器工厂GsonConverterFactory、自定义2数据转换器工厂....// 注
//1. 获取合适的网络请求适配器和数据转换器都是从adapterFactories和converterFactories集合的首位-末位开始遍历
// 因此集合中的工厂位置越靠前就拥有越高的使用权限// 最终返回一个Retrofit的对象并传入上述已经配置好的成员变量return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,callbackExecutor, validateEagerly);}
至此步骤5分析完毕通过前面步骤设置的变量将Retrofit类的所有成员变量都配置完毕。 所以成功创建了Retrofit的实例
总结
平台类型对象Platform - Android网络请求的url地址baseUrl网络请求工厂callFactory 默认使用OkHttpCall 网络请求适配器工厂的集合adapterFactories 本质是配置了网络请求适配器工厂- 默认是ExecutorCallAdapterFactory 数据转换器工厂的集合converterFactories 本质是配置了数据转换器工厂 回调方法执行器callbackExecutor 默认回调方法执行器作用是切换线程子线程 - 主线程 由于使用了建造者模式所以开发者并不需要关心配置细节就可以创建好Retrofit实例建造者模式get。 在创建Retrofit对象时你可以通过更多更灵活的方式去处理你的需求如使用不同的Converter、使用不同的CallAdapter这也就提供了你使用RxJava来调用Retrofit的可能
2.2.2创建网络请求接口的实例
外观模式 代理模式 使用外观模式进行访问里面用了代理模式 1.外观模式 外观模式定义一个统一接口外部与通过该统一的接口对子系统里的其他接口进行访问。 Retrofit对象的外观门店 retrofit.create() 通过这一外观方法就可以在内部调用各个方法创建网络请求接口的实例和配置网络请求参数 大大降低了系统的耦合度 2. 代理模式
代理模式通过访问代理对象的方式来间接访问目标对象 分为静态代理 动态代理 静态代理代理类在程序运行前已经存在的代理方式动态代理代理类在程序运行前不存在、运行时由程序动态生成的代理方式 return (T) roxy.newProxyInstance(ClassLoader loader, Class?[] interfaces, InvocationHandler invocationHandler)通过代理模式中的动态代理模式动态生成网络请求接口的代理类并将代理类的实例创建交给InvocationHandler类 作为具体的实现并最终返回一个动态代理对象。 生成实例过程中含有生成实现类的缓存机制单例模式下面会详细分析 使用动态代理的好处 当NetService对象调用getCall接口中方法时会进行拦截调用都会集中转发到 InvocationHandler#invoke 可集中进行处理获得网络请求接口实例上的所有注解更方便封装ServiceMethod 使用步骤
-- JavaBean.java --
public class JavaBean {.. // 这里就不介绍了}-- 步骤2定义网络请求的接口类 --
-- AccessApi.java --
public interface AccessApi {// 注解GET采用Get方法发送网络请求// Retrofit把网络请求的URL分成了2部分1部分baseurl放在创建Retrofit对象时设置另一部分在网络请求接口设置即这里// 如果接口里的URL是一个完整的网址那么放在创建Retrofit对象时设置的部分可以不设置GET(openapi.do?keyfromYanzhikaikey2032414398typedatadoctypejsonversion1.1qcar)// 接受网络请求数据的方法CallJavaBean getCall();// 返回类型为Call**是解析得到的数据类型即JavaBean
}-- 步骤3在MainActivity创建接口类实例 --
AccessApi NetService retrofit.create(AccessApi.class);-- 步骤4对发送请求的url进行封装即生成最终的网络请求对象 -- CallJavaBean call NetService.getCall();
源码分析
下面主要分析步骤3和步骤4
-- 步骤3在MainActivity创建接口类实例 --
AccessApi NetService retrofit.create(NetService.class);-- 步骤4对发送请求的url进行封装即生成最终的网络请求对象 -- CallJavaBean call NetService.getCall();步骤3 public T T create(final ClassT service) {if (validateEagerly) { // 判断是否需要提前验证eagerlyValidateMethods(service); // 具体方法作用// 1. 给接口中每个方法的注解进行解析并得到一个ServiceMethod对象// 2. 以Method为键将该对象存入LinkedHashMap集合中// 特别注意如果不是提前验证则进行动态解析对应方法下面会详细说明得到一个ServiceMethod对象最后存入到LinkedHashMap集合中类似延迟加载默认} // 创建了网络请求接口的动态代理对象即通过动态代理创建网络请求接口的实例 并最终返回// 该动态代理是为了拿到网络请求接口实例上所有注解return (T) Proxy.newProxyInstance(service.getClassLoader(), // 动态生成接口的实现类 new Class?[] { service }, // 动态创建实例new InvocationHandler() { // 将代理类的实现交给 InvocationHandler类作为具体的实现下面会解释private final Platform platform Platform.get();// 在 InvocationHandler类的invoke实现中除了执行真正的逻辑如再次转发给真正的实现类对象还可以进行一些有用的操作// 如统计执行时间、进行初始化和清理、对接口调用进行检查等。Override public Object invoke(Object proxy, Method method, Object... args)throws Throwable {// 下面会详细介绍 invoke的实现// 即下面三行代码ServiceMethod serviceMethod loadServiceMethod(method); OkHttpCall okHttpCall new OkHttpCall(serviceMethod, args);return serviceMethod.callAdapter.adapt(okHttpCall);}});}// 特别注意
// return (T) roxy.newProxyInstance(ClassLoader loader, Class?[] interfaces, InvocationHandler invocationHandler)
// 可以解读为getProxyClass(loader, interfaces) .getConstructor(InvocationHandler.class).newInstance(invocationHandler);
// 即通过动态生成的代理类调用interfaces接口的方法实际上是通过调用InvocationHandler对象的invoke来完成指定的功能
// 先记住结论在讲解步骤4的时候会再次详细说明-- 关注点1eagerlyValidateMethods --
private void eagerlyValidateMethods(Class? service) { Platform platform Platform.get(); for (Method method : service.getDeclaredMethods()) { if (!platform.isDefaultMethod(method)) { loadServiceMethod(method); } // 将传入的ServiceMethod对象加入LinkedHashMapMethod, ServiceMethod集合// 使用LinkedHashMap集合的好处lruEntries.values().iterator().next()获取到的是集合最不经常用到的元素提供了一种Lru算法的实现}
}
步骤4
Call call NetService.getCall();
NetService对象实际上是动态代理对象Proxy.newProxyInstance步骤3中已说明并不是真正的网络请求接口创建的对象当NetService对象调用getCall时会被动态代理对象Proxy.newProxyInstance拦截然后调用自身的InvocationHandler # invokeinvoke(Object proxy, Method method, Object… args)会传入3个参数Object proxy:代理对象、 Method method调用的getCall() Object… args方法的参数即getCall中的接下来利用Java反射获取到getCall的注解信息配合args参数创建ServiceMethod对象。
最终创建并返回一个OkHttpCall类型的Call对象 OkHttpCall类是OkHttp的包装类 创建了OkHttpCall类型的Call对象还不能发送网络请求需要创建Request对象才能发送网络请求 总结
Retrofit采用了 外观模式 统一调用创建网络请求接口实例和网络请求参数配置的方法具体细节是
动态创建网络请求接口的实例代理模式 - 动态代理创建 serviceMethod 对象建造者模式 单例模式缓存机制对 serviceMethod 对象进行网络请求参数配置通过解析网络请求接口方法的参数、返回值和注解类型从Retrofit对象中获取对应的网络请求的url地址、网络请求执行器、网络请求适配器 数据转换器。策略模式对 serviceMethod 对象加入线程切换的操作便于接收数据后通过Handler从子线程切换到主线程从而对返回数据结果进行处理装饰模式最终创建并返回一个OkHttpCall类型的网络请求对象
2.2.3执行网络请求
Retrofit默认使用OkHttp即OkHttpCall类实现了 retrofit2.Call接口 但可以自定义选择自己需要的Call类 OkHttpCall提供了两种网络请求方式 同步请求OkHttpCall.execute()异步请求OkHttpCall.enqueue()
同步请求OkHttpCall.execute()
1.发送请求过程
步骤1对网络请求接口的方法中的每个参数利用对应ParameterHandler进行解析再根据ServiceMethod对象创建一个OkHttp的Request对象步骤2使用OkHttp的Request发送网络请求步骤3对返回的数据使用之前设置的数据转换器GsonConverterFactory解析返回的数据最终得到一个Response对象
2.具体使用
ResponseJavaBean response call.execute(); 上面简单的一行代码其实包含了整个发送网络同步请求的三个步骤。
3.源码分析
Override
public ResponseT execute() throws IOException {okhttp3.Call call;// 设置同步锁synchronized (this) {call rawCall;if (call null) {try {call rawCall createRawCall();// 步骤1创建一个OkHttp的Request对象请求 --关注1} catch (IOException | RuntimeException e) {creationFailure e;throw e;}}}return parseResponse(call.execute());// 步骤2调用OkHttpCall的execute()发送网络请求同步// 步骤3解析网络请求返回的数据parseResponse --关注2
}-- 关注1createRawCall() --
private okhttp3.Call createRawCall() throws IOException {Request request serviceMethod.toRequest(args);// 从ServiceMethod的toRequest返回一个Request对象okhttp3.Call call serviceMethod.callFactory.newCall(request);// 根据serviceMethod和request对象创建 一个okhttp3.Requestif (call null) {throw new NullPointerException(Call.Factory returned null.);}return call;
}-- 关注2parseResponse--
ResponseT parseResponse(okhttp3.Response rawResponse) throws IOException {ResponseBody rawBody rawResponse.body();rawResponse rawResponse.newBuilder().body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())).build();// 收到返回数据后进行状态码检查// 具体关于状态码说明下面会详细介绍int code rawResponse.code();if (code 200 || code 300) {}if (code 204 || code 205) {return Response.success(null, rawResponse);}ExceptionCatchingRequestBody catchingBody new ExceptionCatchingRequestBody(rawBody);try {T body serviceMethod.toResponse(catchingBody);// 等Http请求返回后 通过状态码检查后将response body传入ServiceMethod中ServiceMethod通过调用Converter接口之前设置的GsonConverterFactory将response body转成一个Java对象即解析返回的数据// 生成Response类return Response.success(body, rawResponse);} catch (RuntimeException e) {... // 异常处理}
}特别注意
ServiceMethod几乎保存了一个网络请求所需要的数据发送网络请求时OkHttpCall需要从ServiceMethod中获得一个Request对象解析数据时还需要通过ServiceMethod使用Converter数据转换器转换成Java对象进行数据解析 为了提高效率Retrofit还会对解析过的请求ServiceMethod进行缓存存放在MapMethod, ServiceMethod serviceMethodCache new LinkedHashMap();对象中即第二步提到的单例模式 关于状态码检查时的状态码说明
异步请求OkHttpCall.enqueue()
1.发送请求过程
步骤1对网络请求接口的方法中的每个参数利用对应ParameterHandler进行解析再根据ServiceMethod对象创建一个OkHttp的Request对象步骤2使用OkHttp的Request发送网络请求步骤3对返回的数据使用之前设置的数据转换器GsonConverterFactory解析返回的数据最终得到一个Response对象步骤4进行线程切换从而在主线程处理返回的数据结果 若使用了RxJava则直接回调到主线程 异步请求的过程跟同步请求类似唯一不同之处在于异步请求会将回调方法交给回调执行器在指定的线程中执行。 指定的线程此处是指主线程UI线程 2.具体使用
call.enqueue(new CallbackJavaBean() {Overridepublic void onResponse(CallJavaBean call, ResponseJavaBean response) {System.out.println(response.isSuccessful());if (response.isSuccessful()) {response.body().show();}else {try {System.out.println(response.errorBody().string());} catch (IOException e) {e.printStackTrace();} ;}}从上面分析有call是一个静态代理使用静态代理的作用是在okhttpCall发送网络请求的前后进行额外操作 这里的额外操作是线程切换即将子线程切换到主线程从而在主线程对返回的数据结果进行处理 3.源码分析
-- call.enqueue解析 --
Override
public void enqueue(final CallbackT callback) {delegate.enqueue(new CallbackT() {// 使用静态代理 delegate进行异步请求 -分析1// 等下记得回来Override public void onResponse(CallT call, final ResponseT response) {// 步骤4线程切换从而在主线程显示结果callbackExecutor.execute(new Runnable() {// 最后Okhttp的异步请求结果返回到callbackExecutor// callbackExecutor.execute通过Handler异步回调将结果传回到主线程进行处理如显示在Activity等等即进行了线程切换// 具体是如何做线程切换 -分析2Override public void run() {if (delegate.isCanceled()) {callback.onFailure(ExecutorCallbackCall.this, new IOException(Canceled));} else {callback.onResponse(ExecutorCallbackCall.this, response);}}});}Override public void onFailure(CallT call, final Throwable t) {callbackExecutor.execute(new Runnable() {Override public void run() {callback.onFailure(ExecutorCallbackCall.this, t);}});}});}-- 分析1delegate.enqueue解析 --
Override
public void enqueue(final CallbackT callback) {okhttp3.Call call;Throwable failure;// 步骤1创建OkHttp的Request对象再封装成OkHttp.call// delegate代理在网络请求前的动作创建OkHttp的Request对象再封装成OkHttp.callsynchronized (this) {if (executed) throw new IllegalStateException(Already executed.);executed true;call rawCall;failure creationFailure;if (call null failure null) {try {call rawCall createRawCall(); // 创建OkHttp的Request对象再封装成OkHttp.call// 方法同发送同步请求此处不作过多描述 } catch (Throwable t) {failure creationFailure t;}}// 步骤2发送网络请求// delegate是OkHttpcall的静态代理// delegate静态代理最终还是调用Okhttp.enqueue进行网络请求call.enqueue(new okhttp3.Callback() {Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)throws IOException {ResponseT response;try {// 步骤3解析返回数据response parseResponse(rawResponse);} catch (Throwable e) {callFailure(e);return;}callSuccess(response);}Override public void onFailure(okhttp3.Call call, IOException e) {try {callback.onFailure(OkHttpCall.this, e);} catch (Throwable t) {t.printStackTrace();}}private void callFailure(Throwable e) {try {callback.onFailure(OkHttpCall.this, e);} catch (Throwable t) {t.printStackTrace();}}private void callSuccess(ResponseT response) {try {callback.onResponse(OkHttpCall.this, response);} catch (Throwable t) {t.printStackTrace();}}});}// 请回去上面分析1的起点-- 分析2异步请求后的线程切换--
// 线程切换是通过一开始创建Retrofit对象时Platform在检测到运行环境是Android时进行创建的之前已分析过
// 采用适配器模式
static class Android extends Platform {// 创建默认的回调执行器工厂// 如果不将RxJava和Retrofit一起使用一般都是使用该默认的CallAdapter.Factory// 后面会对RxJava和Retrofit一起使用的情况进行分析OverrideCallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {return new ExecutorCallAdapterFactory(callbackExecutor);}Override public Executor defaultCallbackExecutor() {// 返回一个默认的回调方法执行器// 该执行器负责在主线程UI线程中执行回调方法return new MainThreadExecutor();}// 获取主线程Handlerstatic class MainThreadExecutor implements Executor {private final Handler handler new Handler(Looper.getMainLooper());Override public void execute(Runnable r) {// Retrofit获取了主线程的handler// 然后在UI线程执行网络请求回调后的数据显示等操作。handler.post(r);}}// 切换线程的流程
// 1. 回调ExecutorCallAdapterFactory生成了一个ExecutorCallbackCall对象
// 2. 通过调用ExecutorCallbackCall.enqueue(CallBack)从而调用MainThreadExecutor的execute()通过handler切换到主线程处理返回结果如显示在Activity等等}以上便是整个以 异步方式发送网络请求的过程。 三、总结
Retrofit 将 Http请求 抽象 成 Java接口在接口里用 注解 描述和配置 网络请求参数用动态代理 的方式动态将网络请求接口的注解 解析 成HTTP请求最后执行HTTP请求