Retrofit基本用法.doc_第1页
Retrofit基本用法.doc_第2页
Retrofit基本用法.doc_第3页
Retrofit基本用法.doc_第4页
Retrofit基本用法.doc_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

透过Retrofit使用看其源码设计模式Retrofit基本用法我以用户登录作为示例:声明接口首先我们先定义一个登录服务接口LoginService,如下:public interface LoginService FormUrlEncoded POST(login) Call login(Field(username) String name, Field(password) String password);创建Retrofit对象Retrofit retrofit = new Retrofit.Builder() .baseUrl() .addConverterFactory(GsonConverterFactory.create() .build();发起请求LoginService service = retrofit.create(LoginService.class);Call call = service.login(user, pwd);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和ExecutorExecutorCallAdapterFactory: Android平台下的默认CallAdapter.Factory实现ServiceMethod: 解析接口服务所有注解、生成请求对象Request、解析请求结果ResponseParameterHandler: 服务接口方法(login()参数解析处理器,配合ServiceMethod进行服务接口参数注解解析RequestBuilder: 根据参数和URL构造请求需要的OkHttp.Request对象以上就是Retrofit源码实现中比较关键的10个类及其相关作用使用流程 实现 设计模式Builder模式创建RetrofitRetrofit场景Retrofit retrofit = new Retrofit.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过程中有这样一行代码:Retrofit retrofit = new Retrofit.Builder().build();从代码可以看到在创建Retrofit时得先根据Retrofit.Builder内部类的默认构造方法Retrofit.Builder()创建一个Builder对象,所以我们来看看这个默认构造方法里都做了些什么事:public Builder() this(Platform.get();OK,我们再来看看我们前面说到的Platform这个平台类的静态方法get()/静态实例对象,类加载就确定了private static final Platform PLATFORM = findPlatform(); static Platform get() return PLATFORM; private static Platform findPlatform() try Class.forName(android.os.Build); if (Build.VERSION.SDK_INT != 0) return new Android(); catch (ClassNotFoundException ignored) try Class.forName(java.util.Optional); return new Java8(); catch (ClassNotFoundException ignored) try Class.forName(org.robovm.apple.foundation.NSObject); return new IOS(); catch (ClassNotFoundException ignored) return new Platform(); .通过上面的代码我们可以很明确的知道,在Platform类加载的时候它就通过反射的机制确定了当前运行的平台是属于哪一个,是Android,是Java8还是iOS,并生成对应的平台类的实例,get()方法是用来获取当前的平台类的实例。目前,我们只关注Android平台下的Platform实例,我们也来看看Android平台类中做了些什么:static class Android extends Platform Override public Executor defaultCallbackExecutor() return new MainThreadExecutor(); Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) return new ExecutorCallAdapterFactory(callbackExecutor); static class MainThreadExecutor implements Executor private final Handler handler = new Handler(Looper.getMainLooper(); Override public void execute(Runnable r) handler.post(r); 可以看到Android类中重写了Platform类的两个方法defaultCallbackExecutor()和defaultCallAdapterFactory(Executor callbackExecutor) 1. 前者就是用来返回当前平台下默认的Executor,这Android平台下就是MainThreadExecutor这个类的实例,可以看到这个执行器主要就是用来进行线程切换的,因为我们知道安卓平台下所有的UI操作都必须在UI线程中执行。 2. 后者就是用来返回当前平台下默认的CallAdapter.Factory 3. 当然你也可以不使用这两个默认值,都可以在创建Retrofit过程中自定义配置自己需要的相关实例Retrofit创建流程 ExecutorCallAdapterFactory看完Platform之后紧接着我们再来看看Android平台下默认的CallAdapter.Factory实现ExecutorCallAdapterFactory都做了些什么,这里只贴关键代码:public interface CallAdapter abstract class Factory public abstract CallAdapter get(Type returnType, Annotation annotations, Retrofit retrofit); . final class ExecutorCallAdapterFactory extends CallAdapter.Factory final Executor callbackExecutor;/对应默认的MainThreadExecutor ExecutorCallAdapterFactory(Executor callbackExecutor) this.callbackExecutor = callbackExecutor; Override public CallAdapterCall get(Type returnType, Annotation annotations, Retrofit retrofit) . return new CallAdapterCall() Override public Type responseType() return responseType; Override public Call adapt(Call call) return new ExecutorCallbackCall(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使用工厂方法模式带来的好处。工厂方法模式优缺点优点 只关注产品工厂即可,不需要关注产品如何创建,由工厂确定如何创建扩展性好,新增产品时,只需要新增一个具体工厂和具体产品缺点 新增产品时,需要新增具体工厂和具体产品类,使系统变得庞大系统中加入抽象层,增加了系统的抽象性和理解难度适配器模式 CallAdapterRetrofit场景先来看看CallAdapter在Retrofit中的使用场景public interface CallAdapter public Type responseType(); public Call adapt(Call call);/ExecutorCallAdapterFactory中生成CallAdapter实例return new CallAdapterCall() Override public Type responseType() return responseType; Override public Call adapt(Call call) return new ExecutorCallbackCall(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实例return new CallAdapterCall() Override public Type responseType() return responseType; Override public Call adapt(Call call) return new ExecutorCallbackCall(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接口的实现静态代理模式 ExecutorCallbackCallRetrofit场景还是先来看看Retrofit中使用ExecutorCallbackCall的场景/ExecutorCallAdapterFactory中生成CallAdapter实例return new CallAdapterCall() . Override public Call adapt(Call call) return new ExecutorCallbackCall(callbackExecutor, call); ;在上面CallAdapter实现中,可以发现它将OkHttpCall适配成了一个新的Call实例:ExecutorCallbackCall,所以我们接着看看ExecutorCallbackCall的具体实现代码static final class ExecutorCallbackCall implements Call final Executor callbackExecutor;/Android平台下的Executor:MainThreadExecutor final Call delegate;/网络实际执行者OkHttpCall实例 ExecutorCallbackCall(Executor callbackExecutor, Call delegate) this.callbackExecutor = callbackExecutor; this.delegate = delegate; Override public void enqueue(final Callback callback) if (callback = null) throw new NullPointerException(callback = null); delegate.enqueue(new Callback() Override public void onResponse(Call call, final Response response) /Android平台下此处进行了线程切换 callbackExecutor.execute(new Runnable() Override public void run() if (delegate.isCanceled() callback.onFailure(ExecutorCallbackCall.this, new IOException(Canceled); else callback.onResponse(ExecutorCallbackCall.this, response); ); Override public void onFailure(Call call, final Throwable t) /Android平台下此处进行了线程切换 callbackExecutor.execute(new Runnable() Override public void run() callback.onFailure(ExecutorCallbackCall.this, t); ); ); Override public boolean isExecuted() return delegate.isExecuted(); Override public Response execute() throws IOException return delegate.execute(); Override public void cancel() delegate.cancel(); Override public boolean isCanceled() return delegate.isCanceled(); SuppressWarnings(CloneDoesntCallSuperClone) / Performing deep clone. Override public Call clone() return new ExecutorCallbackCall(callbackExecutor, delegate.clone(); Override public Request request() return delegate.request(); 可以看到我们通过login()方法拿到Call实例(也就是ExecutorCallbackCall)之后,在执行网络请求时,在ExecutorCallbackCall的实现中其实都是将具体操作委托给OkHttpCall在执行。所以Retrofit在ExecutorCallbackCall中又使用了一种设计模式:静态代理模式静态代理模式定义为其他对象提供一种代理以控制对这个对象的访问静态代理模式使用场景无法访问或不想直接访问某个对象静态代理模式类图这里写图片描述Retrofit中的静态代理Retrofit中使用ExecutorCallbackCall代理OkHttpCall具体请求操作,可以将Call的使用与底层实现进行解耦,不用关心底层具体请求接口的实现,所以如果将来出现了一个比OkHttp更好的网络请求库,我们完全可以将OkHttp替换掉,即便这样也不会影响外部API接口在项目中的使用。静态代理的优缺点优点 协调调用者与被调用者,降低系统耦合度减小外部接口与内部接口实现的关联,降低耦合缺点 委托对象与代理对象需要实现相同的接口,当接口类增加方法时,除了所有实现类需要增加该方法外,所有代理类也需要实现此方法,增加了维护难度一个代理类只能代理一种类型的对象动态代理 Retrofit.create()先看下Retrofit.create()方法的具体实现代码:public T create(final Class 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 . ServiceMethod serviceMethod = loadServiceMethod(method); OkHttpCall okHttpCall = new OHttpCall(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); );相信很多人在刚开始用Retrofit时都会有一点疑问,我们明明声明的是接口,为什么通过create()方法就能创建出一个对象实例呢? 通过上面的实现源码我们找到了答案,那就是使用了JDK中提供的动态代理机制,它会在运行过程中为我们声明的服务接口动态的创建出一个代理对象,以便实现我们的请求操作。我个人认为这是Retrofit框架得以实现的一个核心之处,另外一个核心之处就是其完善的注解机制,关于其注解本文就不说,主要就是一些注解的声明和解析,比较简单,感兴趣的可以去看看。上面的源码中我们可以看到,运行过程中得到服务接口的代理对象之后,当我们调用login()这样的接口方法时,其实真实执行的是上面源码中写的invoke()方法,所以我们调用login()方法时其实是执行了如下三步: 1. 根据反射得到接口方法Method对象生成对应的ServiceMethod对象,该对象会对该声明方法上的所有方法注解、参数注解进行解析以得到一个请求所需要的所有信息 2. 得到ServiceMethod对象之后,会根据该对象和方法调用时传递的参数生成OkHttpCall对象,也就是具体的网络实施者 3. 将OkHttpCall作为CallAdapter适配器中adapt()方法的参数传递给CallAdapter进行适配,最后得到我们所需要的ExecutorCallbackCall对象,也就是调用login()方法得到的Call实例对象动态代理使用场景静态代理特点一个代理对应一种类型,如果有多个类需要代理则需要多个代理,而且维护成本高,而动态代理就是来解决此类问题动态代理特点运行期由JVM通过反射机制动态生成,可以代理多种类型,代码复用性高。但是只能代理Java接口,不能代理Java实现类。Call.enqueue() & Call.execute()实现前面从Retrofit的配置、创建、调用接口方法得到Call实例,基本用法都已经讲的差不多了,现在我们来看基本用法的最后一步Call.enqueue() & Call.execute()前面讲过调用接口方法比如login()时,Android平台下默认得到的是ExecutorCallbackCall实例,而ExecutorCallbackCall实例中执行网络请求的实际上又是OkHttpCall,所以我们来看OkHttpCall中的Call.enqueue() & Call.execute()两个方法的实现,我以Call.enqueue()为例,另外一个大家可以自己去看看下面是该方法实现的关键代码:OkHttpCall.enqueue()Override public void enqueue(final Callback callback) . okhttp3.Call call; Throwable failure; synchronized (this) if (executed) throw new IllegalStateException(Already executed.); executed = true; call = rawCall; failure = creationFailure; if (call = null & failure = null) try /如果okhttp3.Call为空,则先创建该实例 call = rawCall = createRawCall(); catch (Throwable t) failure = creationFailure = t; . /又讲网络执行转交给okhttp3.Call实例来执行 call.enqueue(new okhttp3.Callback() Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) throws IOException Response response; try /将okhttp3.Response结果包装成Retrofit中的结果对象Response response = parseResponse(rawResponse); catch (Throwable e) callFailure(e); return; callSuccess(response); Override public void onFailure(okhttp3.Call call, IOException e) . private void callFailure(Throwable e) . private void callSuccess(Response response) . ); 前面介绍关键类时说过OkHttpCall底层网络执行其实是OkHttp.Call在执行,从上面的代码我们就可以看出来(代码关键地方我加了注释),上面代码关键第一步是先创建一个okhttp3.call实例,所以我们同样看看创建okhttp3.call实例的代码是怎么实现的private okhttp3.Call createRawCall() throws IOException Request request = serviceMethod.toRequest(args); okhttp3.Call call = serviceMethod.callFactory.newCall(request); . return call; 通过上面的createRawCall()方法实现我们可以发现,它会首先通过ServiceMethod.toRequest()方法生成一个OkHttp.Request对象(这部分代码比较简单,我就不细说了),然后根据ServiceMethod中的成员变量CallFactory创建一个okhttp3.Call实例。但是这个CallFactory是怎么来的呢?其实我们可以猜到这个CallFactory实例就是OkHttpClient实例。但是我们还是看看ServiceMethod的创建过程ServiceMethod创建/在Retrofit.create()方法实现的第一步就是通过loadServiceMethod()方法创建ServiceMethod,这是其实现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; /下面是ServiceMethod相关关键代码final class ServiceMethod final okhttp3.Call.Factory callFactory; ServiceMethod(Builder builder) this.callFactory = builder.retrofit.callFactory(); this.callAdapter = builder.callAdapter; TUrl = builder.retrofit.baseUrl(); this.responseConverter = builder.responseConverter; . static final class Builder public Builder(Retrofit retrofit, Method method) this.retrofit = retrofit; this.method = method; . public ServiceMethod build() /创建CallAdapter callAdapter = createCallAdapter(); /得到请求结果返回类型,接口方法声明 responseType = callAdapter.responseType(); . /创建得到Converter结果转换器 responseConverter = createResponseConverter(); . return new ServiceMethod(this); 通过上面的ServiceMethod创建过程的相关代码可以看出,ServiceMethod中的实例变量callFactory其实是调用Retrofit.callFactory()方法所得,大家也可以看看上面我注释的CallAdapter和Converter的创建过程,所以我们再来看看这个方法的实现public okhttp3.Call.Factory callFactory() return callFactory;可以看到该方法只是返回了Retrofit中的callFactory实例,同样,我们再来看看Retrofit中的callFactory实例是怎么来的public final class Retrofit private final okhttp3.Call.Factory callFactory; . Retrofit(okhttp3.Call.Factory callFactory, .) this.callFactory = callFactory; . public static final class Builder private okhttp3.Call.Factory callFactory; . public Builder client(OkHttpClient client) return callFactory(checkNotNull(client, client = null); public Builder callFactory(okhttp3.Call.Factory factory) this.callFactory = checkNotNull

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论