Retrofit基本用法.docx
- 文档编号:15966501
- 上传时间:2023-07-09
- 格式:DOCX
- 页数:26
- 大小:25.16KB
Retrofit基本用法.docx
《Retrofit基本用法.docx》由会员分享,可在线阅读,更多相关《Retrofit基本用法.docx(26页珍藏版)》请在冰点文库上搜索。
Retrofit基本用法
透过Retrofit使用看其源码设计模式
Retrofit基本用法
我以用户登录作为示例:
声明接口
首先我们先定义一个登录服务接口LoginService,如下:
publicinterfaceLoginService{
@FormUrlEncoded
@POST("login")
Call
}
创建Retrofit对象
Retrofitretrofit=newRetrofit.Builder()
.baseUrl("")
.addConverterFactory(GsonConverterFactory.create())
.build();
发起请求
LoginServiceservice=retrofit.create(LoginService.class);
Call
call.execute()或call.enqueue()
Retrofit关键类
在讲Retrofit实现原理之前,我先说下Retrofit里面涉及到几个关键类都是干什么用的
Retorift:
负责配置请求过程中的基本参数,如:
请求地址,结果转换器,自定义OKHttpClient等,同时还会生成请求接口对象
Call:
网络请求执行者(Retrofit.Call),比如:
上面示例中最后调用login方法得到的Call对象就是此接口的实例
OkHttpCall:
此类是Retrofit.Call接口的实现,示例中最后调用login方法得到的Call对象就是此类的实例。
但是其底层网络请求执行都是通过OkHttp.Call接口间接执行的,也就是说OkHttpCall是对OkHttp.Call网络请求功能的封装。
Converter&Converter.Factory:
分别负责网络请求结果转换以及生成Converter转换器
CallAdapter&CallAdapter.Factory:
分别负责对Retrofit.Call实例(OkHttpCall)进行适配及生成CallAdapter适配器
Platform:
确定Retrofit当前运行平台,以及确定当前平台默认的的CallAdapter.Factory和Executor
ExecutorCallAdapterFactory:
Android平台下的默认CallAdapter.Factory实现
ServiceMethod:
解析接口服务所有注解、生成请求对象Request、解析请求结果Response
ParameterHandler:
服务接口方法(login())参数解析处理器,配合ServiceMethod进行服务接口参数注解解析
RequestBuilder:
根据参数和URL构造请求需要的OkHttp.Request对象
以上就是Retrofit源码实现中比较关键的10个类及其相关作用
使用流程>>实现>>设计模式
Builder模式创建Retrofit
Retrofit场景
Retrofitretrofit=newRetrofit.Builder()
.baseUrl("")
.addConverterFactory(GsonConverterFactory.create())
.build();
上面代码的对象创建方式看着是不是似曾相识,看着很眼熟,没错,Android里面的Dialog的创建就是使用的这种方式:
Builder模式
Builder模式定义
将一个复杂对象的构建与它的表示分离,使得同样的构建可以创建不同的表示
Builder模式使用场景
相同的方法不同的执行顺序产生不同的结果
多个部件都可以装配到一个对象中,但是产生的结果不同
Builder模式类图
这里写图片描述
Retrofit中的Builder模式
Retrofit中的Builder模式是简化版的Builder模式,省略了抽象建造者和指挥者
不同的配置会对Retrofit产生不同的影响,如果通过addCallAdapterFactory()配置CallAdapterFactory和不配置CallAdapterFactory会对Retrofit产生完全不同的影响。
如果Retrofit中使用构造方法的方式创建对象,则需要实现多个不同参数的构造方法,而使用构造方法创建对象时如果参数太多,很多时候参数代表的意思是不太理解的,总归来说就是创建过程不直观。
Builder模式优缺点
优点:
不需要知道产品内部的组成细节,产品与创建过程解耦
分步组装产品,使得产品的创建过程更精细更清晰
容易扩展,新产品只需要新建一个建造者即可
缺点:
Builder模式创建的产品差异性小,使用范围受限制
不同的产品会产生多个建造者和指挥者
Retrofit创建流程>>Platform
在创建Retrofit过程中有这样一行代码:
Retrofitretrofit=newRetrofit.Builder()
...
.build();
从代码可以看到在创建Retrofit时得先根据Retrofit.Builder内部类的默认构造方法Retrofit.Builder()创建一个Builder对象,所以我们来看看这个默认构造方法里都做了些什么事:
publicBuilder(){
this(Platform.get());
}
OK,我们再来看看我们前面说到的Platform这个平台类的静态方法get()
//静态实例对象,类加载就确定了
privatestaticfinalPlatformPLATFORM=findPlatform();
staticPlatformget(){
returnPLATFORM;
}
privatestaticPlatformfindPlatform(){
try{
Class.forName("android.os.Build");
if(Build.VERSION.SDK_INT!
=0){
returnnewAndroid();
}
}catch(ClassNotFoundExceptionignored){
}
try{
Class.forName("java.util.Optional");
returnnewJava8();
}catch(ClassNotFoundExceptionignored){
}
try{
Class.forName("org.robovm.apple.foundation.NSObject");
returnnewIOS();
}catch(ClassNotFoundExceptionignored){
}
returnnewPlatform();
}
...
}
通过上面的代码我们可以很明确的知道,在Platform类加载的时候它就通过反射的机制确定了当前运行的平台是属于哪一个,是Android,是Java8还是iOS,并生成对应的平台类的实例,get()方法是用来获取当前的平台类的实例。
目前,我们只关注Android平台下的Platform实例,我们也来看看Android平台类中做了些什么:
staticclassAndroidextendsPlatform{
@OverridepublicExecutordefaultCallbackExecutor(){
returnnewMainThreadExecutor();
}
@OverrideCallAdapter.FactorydefaultCallAdapterFactory(ExecutorcallbackExecutor){
returnnewExecutorCallAdapterFactory(callbackExecutor);
}
staticclassMainThreadExecutorimplementsExecutor{
privatefinalHandlerhandler=newHandler(Looper.getMainLooper());
@Overridepublicvoidexecute(Runnabler){
handler.post(r);
}
}
}
可以看到Android类中重写了Platform类的两个方法defaultCallbackExecutor()和defaultCallAdapterFactory(ExecutorcallbackExecutor)
1.前者就是用来返回当前平台下默认的Executor,这Android平台下就是MainThreadExecutor这个类的实例,可以看到这个执行器主要就是用来进行线程切换的,因为我们知道安卓平台下所有的UI操作都必须在UI线程中执行。
2.后者就是用来返回当前平台下默认的CallAdapter.Factory
3.当然你也可以不使用这两个默认值,都可以在创建Retrofit过程中自定义配置自己需要的相关实例
Retrofit创建流程>>ExecutorCallAdapterFactory
看完Platform之后紧接着我们再来看看Android平台下默认的CallAdapter.Factory实现ExecutorCallAdapterFactory都做了些什么,这里只贴关键代码:
publicinterfaceCallAdapter
abstractclassFactory{
publicabstractCallAdapter
>get(TypereturnType,Annotation[]annotations,
Retrofitretrofit);
...
}
}
finalclassExecutorCallAdapterFactoryextendsCallAdapter.Factory{
finalExecutorcallbackExecutor;//对应默认的MainThreadExecutor
ExecutorCallAdapterFactory(ExecutorcallbackExecutor){
this.callbackExecutor=callbackExecutor;
}
@Override
publicCallAdapter >>get(TypereturnType,Annotation[]annotations,Retrofitretrofit){ ... returnnewCallAdapter >>(){ @OverridepublicTyperesponseType(){ returnresponseType; } @Overridepublic returnnewExecutorCallbackCall<>(callbackExecutor,call); } }; } ... } 大家看源码可以发现CallAdapter.Factory工厂是通过get()方法来创建CallAdapter的,所以ExecutorCallAdapterFactory关键代码也是在get()方法的实现上,上面的代码中我们可以看到get()方法返回一个CallAdapter实例,这就是我前面介绍关键类作用时说到的CallAdapter.Factory主要负责生成CallAdapter的实现。 该类中,我们从其类的命名以及代码实现结构上来看,ExecutorCallAdapterFactory其实也使用了一种设计模式,那就是工厂方法模式,其实Retrofit中还有一个地方也使用了工厂方法模式,那就是Converter&Converter.Factory它的实现方式和CallAdapter&CallAdapter.Factory是一样样的。 工厂方式模式(创建CallAdapter&Converter) 本文我就已CallAdapter进行举例,看懂CallAdapter的创建原理之后,再看Converter的创建也就比较简单,都是一样的道理。 Retrofit场景 Retrofit中使用工厂方式模式的场景我在前面讲ExecutorCallAdapterFactory实现的时候已经讲过了,这里就不重复举例了,大家可以对照着源码看下。 工厂方法模式定义 一个用于创建对象的接口,让子类决定实例化哪个类 工厂方法模式使用场景 不需要知道其具体的类名,只需要知道生成它的工厂 一个类通过其子类来决定创建哪个对象 工厂方法模式类图 这里写图片描述 Retrofit中的工厂方法 Retrofit中使用工厂方法模式可以讲CallAdapter的创建与具体实现充分解耦,对于创建我们只需要知道其工厂即可,不需要关注是如何实现 所以我们可以通过addCallAdapterFactory()和addConverterFactory()很方便的自定义我们自己所需要的适配器工厂和数据转换工厂 通过addCallAdapterFactory()可以很方便的让Retrofit支持RxJava特性,而通过addConverterFactory()可以自定义配置们想要的转换器,让我们可以将请求数据结果转换成我们想要的任意类型。 这些就是Retrofit使用工厂方法模式带来的好处。 工厂方法模式优缺点 优点 只关注产品工厂即可,不需要关注产品如何创建,由工厂确定如何创建 扩展性好,新增产品时,只需要新增一个具体工厂和具体产品 缺点 新增产品时,需要新增具体工厂和具体产品类,使系统变得庞大 系统中加入抽象层,增加了系统的抽象性和理解难度 适配器模式>>CallAdapter Retrofit场景 先来看看CallAdapter在Retrofit中的使用场景 publicinterfaceCallAdapter publicTyperesponseType(); public } //ExecutorCallAdapterFactory中生成CallAdapter实例 returnnewCallAdapter >>(){ @OverridepublicTyperesponseType(){ returnresponseType; } @Overridepublic returnnewExecutorCallbackCall<>(callbackExecutor,call); } }; 前面讲到ExecutorCallAdapterFactory会生成一个CallAdapter实例。 而CallAdapter这个名字看着是不是也很眼熟,也有种似曾相识的感觉,没错,CallAdapter与我们在Android中使用ListView或RecyclerView时经常用到的各种Adapter一样也是一个适配器。 那CallAdapter是来适配什么的呢? 还记得前面介绍关键类的时候说到的OkHttpCall吗? CallAdapter就是来适配OkHttpCall实例的,结合上面的代码来说的话在调用CallAdapter.adapt方法时OkHttpCall实例会作为参数传递给adapt方法从而交给CallAdapter去进行适配。 在我前面举的登录示例中,我们调用login()方法得到的Call实例就是CallAdapter适配OkHttpCall之后得到的一个新Call实例对象,至于为什么是这样,我后面会一一讲解,各位看官不要离开 所以Retrofit在这个地方又使用了一种设计模式: 适配器模式 适配器模式定义 将一个类的接口变成客户端所需要的另一个接口,从而使原本因接口不匹配而无法一起工作的两个类可以在一起工作 适配器模式使用场景 需要复用现有类,而现有类不符合系统需求 需要一个统一的输出接口,而输入端类型不可预知 适配器模式类图 这里写图片描述 Retrofit中的适配器模式 //ExecutorCallAdapterFactory中生成CallAdapter实例 returnnewCallAdapter >>(){ @OverridepublicTyperesponseType(){ returnresponseType; } @Overridepublic returnnewExecutorCallbackCall<>(callbackExecutor,call); } }; Android平台下默认的CallAdapter会将OkHttpCall和MainThreadExecutor两个实例对象适配成一个新的Call实例,这个新的Call实例在执行过程中就具备了切换到UI线程的功能。 那Retrofit在这个地方为什么要使用适配器模式将OkHttpCall进行适配了,直接拿过来用不就可以了吗? 前面讲过OkHttpCall仅仅只是对OkHttp.Call执行网络请求操作的封装,没有其他功能,也就是说OkHttpCall也只有网络请求的功能,而Retrofit是支持多个平台的(安卓,Java8,IOS,甚至包括支持RxJava特性),而不同的平台可能具有不同的特性。 如果在请求过程中需要用到这些特性的话,那么单靠OkHttp.Call是无法完成的,而如果在其他地方柔和进这些特性的支持可能就会使得框架结构不那么严谨平台解耦性比较差,甚至有可能会增加更多的接口。 Retrofit通过使用适配器模式将平台特性与OkHttpCall适配成一个最终我们需要的Call实例,这样的话我们在使用过程中只需要关注最后拿到的Call对象,而不需要关注底层这个Call实例到底是什么样的,这也就为我们支持更多的特性提供了可能。 比如对RxJava特性的支持,我们只需要提供一个支持RxJava特性的CallAdapter适配器即可,所以我们就可以通过addCallAdapterFactory()配置我们提供的支持RxJava特性的CallAdapter.Factory 适配器模式优缺点 优点 复用性好,引入适配器类来重用适配者类,无需修改原有代码 增加类的透明性,将适配过程封装在适配器类中,对使用者来说相对透明 灵活性扩展性好,通过配置可以随时更换适配器 缺点 使用适配器会使系统整体不好把握,调的是A接口,却被适配成了B接口的实现 静态代理模式>>ExecutorCallbackCall Retrofit场景 还是先来看看Retrofit中使用ExecutorCallbackCall的场景 //ExecutorCallAdapterFactory中生成CallAdapter实例 returnnewCallAdapter >>(){ ... @Overridepublic returnnewExecutorCallbackCall<>(callbackExecutor,call); } }; 在上面CallAdapter实现中,可以发现它将OkHttpCall适配成了一个新的Call实例: ExecutorCallbackCall,所以我们接着看看ExecutorCallbackCall的具体实现代码 staticfinalclassExecutorCallbackCall finalExecutorcallbackExecutor;//Android平台下的Executor: MainThreadExecutor finalCall ExecutorCallbackCall(ExecutorcallbackExecutor,Call this.callbackExecutor=callbackExecutor; this.delegate=delegate; } @Overridepublicvoidenqueue(finalCallback if(callback==null)thrownewNullPointerException("callback==null"); delegate.enqueue(newCallback @OverridepublicvoidonResponse(Call //Android平台下此处进行了线程切换 callbackExecutor.execute(newRunnable(){ @Overridepublicvoidrun(){ if(delegate.isCanceled()){ callback.onFailure(ExecutorCallbackCall.this,newIOException("Canceled")); }else{ callback.onResponse(ExecutorCallbackCall.this,response); } } }); } @OverridepublicvoidonFailure(Call //Android平台下此处进行了线程切换 callbackExecutor.execute(newRunnable(){ @Overridepublicvoidrun(){ callback.onFailure(ExecutorCallbackCall.this,t); } }); } }); } @OverridepublicbooleanisExecuted(){ returndelegate.isExecuted(); } @OverridepublicResponse
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Retrofit 基本 用法