第一篇:Retrofit主要类UML图
2016-05-06 16:07:09
1.先上一张Retrofit的代码结构图:

可以看到,Retrofit自身的结构很简单,代码量也不是很大。红色框部分是一些注解类,就是一些标记。
简单的看一下客户端是如何使用Retrofit的:
定义接口:
public interface WeatherDataService {
@GET("/wtr-v2/temp/realtime")
Call<MiWeatherData> getMiWeather(@Query("cityId") String cityId);
@GET("/wtr-v2/temp/realtime")
Observable<MiWeatherData> getMiWeatherObservable(@Query("cityId") String cityId);
@GET("/wtr-v2/temp/realtime")
MiWeatherData getMiWeatherCustomCallAdapter(@Query("cityId") String cityId);
}
客户端调用:
private void getWeather() {
retrofit = new Retrofit.Builder()
.baseUrl("http://weatherapi.market.xiaomi.com")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
service = retrofit.create(WeatherDataService.class);
Call<MiWeatherData> result = service.getMiWeather("101010100");
try {
Response<MiWeatherData> r = result.execute();
MiWeatherData data = r.body();
Log.e("David", "ResponseBody data = " + data);
if (data != null) {
Log.e("David", "RxLoaderCallback data = " + data.weatherinfo.SD);
Log.e("David", "RxLoaderCallback data = " + data.weatherinfo.cityid);
Log.e("David", "RxLoaderCallback data = " + data.weatherinfo.WS);
}
} catch (IOException e) {
e.printStackTrace();
}
}
2. 几个主要类的UML简图:
2.1 Retrofit和Retrofit.Factory

Retrofit和ServiceMethod使用了Builder模式(省略了Director和Abstract Product的Builder模式)来构建自己,Retrofit的作用很简单,传入需要的参数,构建一个Retrofit对象,然后通过动态代理的方式,得到我们自定义的方法接口的实例,参数中除了baseUrl之外,其他都是可选的,如果没设置会使用默认值。
ServiceMethod就是我们自己调用的方法做一层封装而已,包括解析方法使用的注解、参数等,同时提供方法,生成网络请求需要的Request和解析请求结果。
2.1 CallAdapter和CallAdapter.Factory

CallAdapt的作用是把Call转变成你想要返回的对象,起作用的是adapt方法,CallAdapter.Factory的作用是获取CallAdapter。ExecutorCallAdapterFactory的CallAdapter会将回调方法放到主线程中执行,DefaultCallAdapterFactory不是。两者的CallAdapter能够接受的返回值类型为Call<T>。很明显,RxJavaCallAdapterFactory的CallAdapter能够接受的返回值是Oservable<T>。如果想让的方法直接返回一个对象,可以自定义一个CallAdapter.Factory。代码如下:
private class MyCallAdapterFactory extends CallAdapter.Factory {
@Override
public CallAdapter<?> get(final Type returnType, Annotation[] annotations, Retrofit retrofit) {
return new CallAdapter<Object>() {
@Override
public Type responseType() {
return returnType;
}
@Override
public <R> Object adapt(Call<R> call) {
try {
return call.execute().body();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
};
}
}
Service方法和CallAdapter的对应关系如下:

2.3 Converter和Converter.Factory

Converter的作用是将网络请求结果ResponseBody转换为我们希望的返回值类型。Converter.Factory的作用是获取Converter,这里很明显采用了静态工厂模式。如果你不设置ConverterFactory,那么调用WeatherDataInterface的三个方法都会崩溃,提示:Could not locate ResponseBody converter for class MiWeatherData。这是因为使用了默认的BuiltInConverters,而我们的方法不满足获取到responseBodyConverter的要求,所以崩溃,代码截图如下:

所以,如果不想设置Converter,那么我们的方法返回值必须为ResponseBody或者Void,如果是ResponseBody,且有@Streaming注解,会使用StreamingResponseBodyConverter,否则使用BufferingResponseBodyConveter。这两者基本都是原封不动的返回ResponseBody。而VoidResponseBodyConverter返回null~感觉这点比较坑,干点什么不好,非要返回null
Retrofit提供了多个Converter供选择,比如将Json转换为Object的GsonConverterFactory,如下图:

这也是Retrofit的一大特点---足够的开放、灵活。
2.4 OkHttpCall

OkHttpCall继承自interface Call,主要的作用是调起执行网络请求以及返回当前请求状态状态,但是真正的网络请求其实在okhttp3.Call接口,接口定义如下:

这个接口的实现类是okhttp3.RealCall,可以发现,Retrofit的Call接口和okhttp3的Call接口定义几乎是完全一样的,目的当然是实现OCP,这样做的好处显而易见:
1.利于扩展,retrofit2.Call接口可以有其他的实现类,不一定非要用OkHttp,只不过OkHttpCall用的恰好是OkHttp而已。
2.解耦,为了实现第一个目的,retrofit2.Call接口的存在就是理所当然的。
2.5 ParameterHandler

这是一个辅助类,用于解析我们自己定义的Method,由于我们是通过注解的方式来表达各种信息,比如请求类型(POST、GET)、Query参数、Body等,因此需要解析出来。不在主线,因此不作分析,但是里面的实现蛮复杂的,是个细致活儿。
2.6 RxJavaCallAdapterFactory分析

CallAdapterFactory的作用及工作机理前面已经介绍过了,RxJavaCallAdapterFactory的作用也是一样的,只不过RxJavaCallAdapterFactory中内部又定义了三种CallAdapter:ResponseCallAdapter、ResultCallAdapter和SimpleCallAdapter,根据返回值类型决定到底使用哪个,代码如下:

本质上处理流程是一致的,都是按照RxJava的套路执行请求并处理返回值的。
关于Retrofit中主要类的分解到此结束,之所以这么繁琐的画UML图,目的是为了更加深入的了解作者设计类的思路,比如作者是如何考虑一个类的功能、边界在哪里等。
第一篇:Retrofit主要类UML图的更多相关文章
- 【面试 JDK】【第一篇】Object类面试详解
1.Object类有哪些方法 1>clone()方法 保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异 ...
- 如何制作一款HTML5 RPG游戏引擎——第一篇,地图类的实现
一,话说天下大事 前不久看到lufy的博客上,有一位朋友想要一个RPG游戏引擎,出于兴趣准备动手做一做.由于我研究lufylegend有一段时间了,对它有一定的依赖性,因此就准备将这个引擎基于lufy ...
- 关于ER图和UML图之间的对比
ER图与UML图 ER图:实体-联系图(Entity-Relation Diagram)用来建立数据模型,在数据库系统概论中属于概念设计阶段,ER图提供了表示实体(即数据对象).属性和联系的方法,用来 ...
- java 线程池第一篇 之 ThreadPoolExcutor
一:什么是线程池? java 线程池是将大量的线程集中管理的类,包括对线程的创建,资源的管理,线程生命周期的管理.当系统中存在大量的异步任务的时候就考虑使用java线程池管理所有的线程.减少系统资源的 ...
- UML图学习之二 类图
类图(ClassDiagrams)是根据系统中的类以及各类之间的关系描述系统的静态视图.类图不仅显示系统内信息的结构,还描述系统内这些信息的行为.类图的一个重要目的是为其他图(如顺序图.交互图)定义一 ...
- eclipse下生成Java类图和时序图,生成UML图
1.安装和使用AmaterasUML 安装AmaterasUML前,需要先安装GEF采用eclipse在线安装方式安装就好.eclipse在线安装GEF的地址:http://download.ecli ...
- java 类与类之间的关系 及uml图
类与接口之间的关系 : 继承 类与类之间的关系 :继承关系 包含关系 类与对象之间的关系 : 实例 UML 类图中类与类之间的关系: 泛化关系(generalization) 关联关系(associ ...
- C++第一篇--类的引入
C++第一篇--类的引入 1. 用C语言输出两个人的信息 Person1.c:通过字符实现 #include <stdio.h> int main(int argc,int **argv) ...
- UML图类,接口之间的关系
UML图类之间的关系(来自大话设计模式中的一张图,代表了类,接口之间的各种关系)
随机推荐
- SYSTick 定时器
CM3 内核的处理器,内部包含了一个 SysTick 定时器,(SysTick 的时钟源自 HCLK 的 8 分频,8个系统时钟周期systick跳一个,即8*1/72M=1/9 us)Sys ...
- shell编程之变量
变量: 变量由字母.数字._ 组成,不能以数字开头 长度不能超过255个字符 在bash中,变量的默认类型是字符串类型 变量分类: 1.用户自定义变量:只在当前shell生效,是局部变量 定义方法: ...
- Maven安装与使用
1.安装Maven 1)官网下载Maven : http://maven.apache.org/download.cgi,解压下载文件 2)配置环境变量 3)验证是否已经安装成功:打开cmd,输入mv ...
- SAP ERP和ORACLE ERP的区别是哪些?
SAP有非常细致深入的标准流程,在流程方面,只要是你想到的问题,SAP都会曾经遇到过并且给出过解决方案.实施SAP比较倾向于改变企业的业务流程来匹配SAP,实现标准化管理. oracle比较灵活,侧重 ...
- js 作用域
js 作用域 js作用域链查找,子函数能取到父函数中定义的变量. 前段时间误写成如下形式: 这只是普通的函数调用,没有父子的关系,child()函数会在全局查找pi变量,没找到所以报错. 最近发现原来 ...
- Connection broken for id 62, my id = 70, error =
启动费zokeeper失败,报错如下:Connection broken for id 62, my id = 70, error = 原因是因为zoo.cfg中server.id不正确. serve ...
- console
你所不知道的 Console 2016-12-19 ZHANGXIANGLIANG JavaScript 转自 https://segmentfault.com/a/119000000672160 1 ...
- psql
1.sudo passwd postgres 2.sudo -u postgres createuser -P django_login 3.su postgres 4.psql 5.CREATE D ...
- 用margin还是padding
用margin还是用padding这个问题是每个学习CSS进阶时的必经之路. CSS边距属性定义元素周围的空间.通过使用单独的属性,可以对上.右.下.左的外边距进行设置.也可以使用简写的外边距属性同时 ...
- Oracle一个事务中的Insert和Update执行顺序
今天碰到了一个奇怪的问题,是关于Oracle一个事务中的Insert和Update语句的执行顺序的问题. 首先详细说明下整个过程: 有三张表:A,B,C,Java代码中有一段代码是先在表A中插入一条数 ...