Android—Retrofit解析
设计模式:
外观模式,构建者模式,工厂模式,代理模式,适配器模式,策略模式,观察者模式
Retrofit网络通信八步骤
- 创建Retrofit实例
- 定义网络请求接口,并为接口中的方法添加注解
- 通过动态代理生成网络请求对象
- 通过网络请求适配器将网络请求对象进行平台适配
- 通过网络请求执行器,发送网络请求(call)
- 通过数据解析器解析数据
- 通过回调执行器,切换线程
- 用户在主线程处理返回结果
@GET("/user/{user}/repos")
Call<ResponseBody> find(@Path("user") String user);//call封装了整个okhttp的请求Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.github.com/").addConverterFactory(GsonConverteractory.create())//.addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();//动态生成代理对象
Request req = retrofit.create(Request.class);
//生成一个OKHttpCall的代理对象
Call<ResponseBody> call = req.find(“Mike”);
//返回结果
Response<ResponseBody> response = call.execute();
先看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, 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<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) loadServiceMethod(method);OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);return serviceMethod.callAdapter.adapt(okHttpCall);}});
}
使用了动态代理,Proxy.newProxyInstance()返回一个代理类对象。
invoke方法接收三个参数,动态代理对象、我们调用的方法、参数数组;
loadServiceMethod方法:
ServiceMethod loadServiceMethod(Method method) {ServiceMethod result;synchronized (serviceMethodCache) {result = serviceMethodCache.get(method);if (result == null) {result = new ServiceMethod.Builder(this, method).build();serviceMethodCache.put(method, result);}}return result;
}
Build类:
public Builder(Retrofit retrofit, Method method) {this.retrofit = retrofit;this.method = method;// 获取 method 中的所有注解this.methodAnnotations = method.getAnnotations();// 获取 method 中方法的参数类型this.parameterTypes = method.getGenericParameterTypes();// 获得参数的值this.parameterAnnotationsArray = method.getParameterAnnotations();
}
build()方法主要内容
// 根据 retrofit 对象的 CallAdapterFactory 为 ServiceMethod 创建一个 callAdapter
callAdapter = createCallAdapter();
// 根据 retrofit 对象创建一个 responseConverter,默认是一个 BuildInConveter
responseConverter = createResponseConverter();
// 解析 method 的所有注解
for (Annotation annotation : methodAnnotations) {parseMethodAnnotation(annotation);
}
所以ServiceMethod主要封装了callAdapter和responseConverter ,对注解进行了解析,对后面网络请求做准备。
看回Create方法的代码
return serviceMethod.callAdapter.adapt(okHttpCall);
最后是调用了callAdapter的adapt方法,如果我们添加了RxJava2CallAdapter,
@Override
public Object adapt(Call<R> call) {Observable<Response<R>> responseObservable = isAsync? new CallEnqueueObservable<>(call): new CallExecuteObservable<>(call);Observable<?> observable;if (isResult) {observable = new ResultObservable<>(responseObservable);} else if (isBody) {observable = new BodyObservable<>(responseObservable);} else {observable = responseObservable;}if (scheduler != null) {observable = observable.subscribeOn(scheduler);}if (isFlowable) {return observable.toFlowable(BackpressureStrategy.LATEST);}if (isSingle) {return observable.singleOrError();}if (isMaybe) {return observable.singleElement();}if (isCompletable) {return observable.ignoreElements();}return observable;
}
所以如果添加了RxJava2CallAdapter就返回observal对象。
Retrofit中还有一个Converter ,与CallAdapter一样重要,用户可以根据需求对这两个进行自由扩展。
Okhttp中服务器返回的数据源就是ResponseBody对象。所以我们的目标就是对ResponseBody进行解析:
T convert(ResponseBody value){//do convert and return t
}
Retrofit不仅可以对ResponseBody进行转换,也可以对RequestBody进行转换;具体其内部提供了一个Convert.Factory:
abstract class Factory {//对ResponseBody进行数据转换的转换器public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,Annotation[] annotations, Retrofit retrofit) {return null;}//将未知数据转换成RequestBody的转换器public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {return null;}//将未知数据转换成String类型的数据转换器public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,Retrofit retrofit) {return null;}
}
开头构建Retrofit对象的
.addConverterFactory(GsonConverterFactory.create()) //添加Gson
就是用来添加Gson对象的
public static GsonConverterFactory create() {return create(new Gson());}public static GsonConverterFactory create(Gson gson) {return new GsonConverterFactory(gson);}class GsonConverterFactory extends Converter.Factory{//持有一个gson对象用来讲原始数据转换成JavaBeanprivate final Gson gson;private GsonConverterFactory(Gson gson) {this.gson = gson;}}
具体转换过程可以看Gson原理分析。
Android—Retrofit解析相关推荐
- Android混淆解析
此文章转载来源https://www.jianshu.com/p/84114b7feb38点击打开链接 Android混淆解析 一.混淆的目的 一款发布到市场的软件原则上都应该做代码混淆. 通过代码混 ...
- Android Retrofit 2.0文件上传
Android Retrofit 实现(图文上传)文字(参数)和多张图片一起上传 使用Retrofit进行文件上传,肯定离不开Part & PartMap. public interface ...
- Android Retrofit 2.0(三)从源码分析原理
Retrofit·特点 性能最好,处理最快 使用REST API时非常方便: 传输层默认就使用OkHttp: 支持NIO: 拥有出色的API文档和社区支持 速度上比volley更快: 如果你的应用程序 ...
- android json解析异常,json数据解析异常而导致网络请求失败的解决办法(其一)
问题概述 笔者在开发过程中临时遇到一个本来仅有web端的项目临时增加Android端,导致后端在出接口时并未考虑Android端的json数据的解析,导致接口是这样的.... 正确请求 { " ...
- Android Retrofit+RxJava 优雅的处理服务器返回异常、错误
Android Retrofit+RxJava 优雅的处理服务器返回异常.错误 参考文章: (1)Android Retrofit+RxJava 优雅的处理服务器返回异常.错误 (2)https:// ...
- Android Retrofit @Streaming 注解失效
Android Retrofit @Streaming 注解失效 问题特征: 即使加了@Streaming方法也不能达到逐步加载大文件数据的效果,产生的效果为下载会有长时间的卡顿,卡顿后,会在极端的时 ...
- Android中解析XML
Android中解析XML 转载于:https://www.cnblogs.com/zhujiabin/p/5868993.html
- android 如何实现无限列表,在Android中解析和创建无限/无限级别的List /子列表中的XML...
在我的Android Application的服务器端应用程序也由我开发.在这个应用程序Android应用程序从服务器请求一些XML并解析它. XML包含描述应用程序中应该有多少标签的信息,并且每个标 ...
- 在linux kernel或android中解析cmdline参数
文章目录 ★★★ 友情链接 : 个人博客导读首页-点击此处 ★★★ Kernel command line: earlycon androidboot.selinux=permissive uart_ ...
最新文章
- cron 工具 每分钟_计划任务 cron和crontab
- linux 命令行简介
- 皮一皮:精致的人生,哪怕拔火罐也要搭配衣服出门...
- 毕业论文 | 便携式环境烟雾监测器(源码、电路图)
- 理解有符号数和无符号数的区别
- windows 10下的kiosk模式
- greenplum 查询出来的数字加减日期_Python实践代码总结第5集(日期相关处理)
- Android Gradle和Gradle插件区别
- PyTorch 1.0 中文文档:数据类型信息
- 软件测试中有关界面测试经验总结
- python和c先学哪个-C和Python我该先学什么?
- C++程序设计方法3:类中的静态成员
- 黄淮学院计算机专业录取分数线2019,黄淮学院2020年录取分数线(附2017-2020年分数线)...
- paip.程序设计--扫号器跑号器结果分类设计
- python编一个答题程序_从0到1使用python开发一个半自动答题小程序的实现
- 利用matlab实现卷积实验报告,matlab卷积实验报告(共8篇).doc
- Python数据处理Tips数据重复值处理常用方法
- 云服务器wim7系统激活,云服务器怎么装win7系统教程
- IP-guard全部22个功能模块简介
- 喝酸奶竟然能预防霉菌性阴道炎
热门文章
- 初中计算机ppt教案,初中计算机ppt教案.doc
- 10G_Ethernet_04 10G Ethernet Subsystem IP 的快速验证(万兆以太网IP的快速验证)
- tp5分布式redis_TP5通过缓存数据到Redis
- cedit多行文本设置透明背景会重叠_PPT脱白教程11期【形状篇2】聊聊形状和文本框的那些事儿~...
- unity添加对象实例_【Unity】6.3 通过 C# 脚本创建和访问游戏对象
- ad20如何画出pcb板大小_多层pcb板是如何抄板的?
- 半导体芯片原厂涨价及调价声明新增了这些!
- 当电路与艺术相结合,美的让人窒息!
- 程序员崩溃的40个瞬间!(动图)
- java并发计数器_浅谈java并发之计数器CountDownLatch