retrofit可以说是如今市面上最火的网络框架,最常用的大概就是retrofit+RxJava+okhttp框架,结合MVP设计模式的经典应用了吧,今天我们只讲retrofit,上一篇已经说过,retrofit的内部其实也是使用了okhttp的
1.使用方法:
(1)创建一个接口作为http请求的api接口
public interface Api { @GET("repos/{owner}/{repo}/contributors") CallcontributorBySimpleGetCall(@Path("owner") String owner,@Path("repo") String repo); }
(2)创建一个Retrofit的实例
(3)调用api接口
private void retrofitHttpGet() throws Exception{ Retrofit retrofit=new Retrofit.Builder().baseUrl("") .build(); Api api=retrofit.create(Api.class); CallresponseBodyCall = api.contributorBySimpleGetCall("owner", "repo"); responseBodyCall.enqueue(new Callback () { @Override public void onResponse(Call call, Response response) { Log.e("返回的数据是:",response.body().toString()); } @Override public void onFailure(Call call, Throwable t) { } }); }
2.源码分析:
讲到retrofit的源码,就不得不提到一个很牛逼的概念,java当中的动态代理
每次我想到java的动态代理,我都会想到一个例子,打个比方,比如说,你喜欢一个美女,想给他表白,情书都写好了,但是你不敢给他,于是拜托我递给她,但是我也喜欢这个美女,所以我在给她情书的时候,在她面前说你是个渣男。在这个过程中,你就是委托类,我就是中介类,美女就勉强当做代理类吧,你委托我干一件事,我在干这件事的前后可以做一些其他的操作,这就是Java的动态代理的概念,接下来就用一个代码实例来说明一下:
public class DTDLTest { public static void main(String args[]) { //创建委托类实例 WTLClass wtlClass=new WTLClass(); //创建中介类实例 ProxyHandler handler=new ProxyHandler(wtlClass); //动态创建代理类 Subject subject= (Subject)Proxy.newProxyInstance(wtlClass.getClass().getClassLoader(), Subject.class.getInterfaces(), handler); //通过代理类对象调用代理类方法,实际上会转到invoke方法调用 subject.doSomething(); } //创建委托类 static class WTLClass implements Subject{ @Override public void doSomething() { System.out.println("干一些事情"); } } //委托类实现的接口 interface Subject{ void doSomething(); } //创建中介类 static class ProxyHandler implements InvocationHandler{ private Object object; public ProxyHandler(Object o) { this.object=o; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("方法调用前干的事"); Object object=method.invoke(proxy,args); System.out.println("方法调用前干的事"); return object; } } }
了解了动态代理之后,接下来就开始分析retrofit的源码了,retrofit的源码有点多,而且有点复杂,我还是先决定把它整个请求网络的流程先梳理一遍:
(1)通过解析 网络请求接口的注解 配置 网络请求参数
(2)通过 动态代理 生成 网络请求对象
(3)通过 网络请求适配器 将 网络请求对象 进行平台适配
(4)通过 网络请求执行器 发送网络请求
(5)通过 数据转换器 解析服务器返回的数据
(6)通过 回调执行器 切换线程(子线程 ->>主线程)
(7)用户在主线程处理返回结果
现在把上面的几个角色一一介绍一遍:
(1)网络请求执行器:也就是我们创建出来的Call对象,它的作用就是创建Http请求,而retrofit中默认使用的就是okhttp3.Call,所以我们知道这里的网络请求执行器其实就是在okhttp里面讲的Call;
(2)网络请求适配器:(CallAdapter),这个就是Call的适配器,因为retrofit要适配各种平台,Android,Rxjava、Guava和java8,所以在retrofit内部配置了四种CallAdapterFactory,ExecutorCallAdapterFactory(Android默认),GuavaCallAdapterFactory,java8CallAdapterFactory,RxjavaCallAdapterFactory,通过这些适配器,可以让retrofit兼容各种平台,适配各种应用场景;
(3)数据转换器 :服务器返回的数据各种各样,retrofit为我们封装了各类数据的转换器,将返回数据解析成我们需要的数据类型;
(4)回调执行器:它的主要作用就是线程转换,把子线程切换到主线程,将最后的okhttp的请求结果通过callbackExecutor使用handler回调给主线程;
接下来就一步步的分析了;
我们先从创建Retrofit对象开始说起,
Retrofit retrofit=new Retrofit.Builder().baseUrl("") .build();
这里很明显是通过build模式建立的,首先看看retrofit的构造器
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl, List这里可以看出,创建一个retrofit的标准就是配置好一些参数,即:converterFactories, List adapterFactories, Executor callbackExecutor, boolean validateEagerly) { this.callFactory = callFactory; this.baseUrl = baseUrl; this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site. this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site. this.callbackExecutor = callbackExecutor; this.validateEagerly = validateEagerly; }
serviceMethod
:包含所有网络请求信息的对象
baseUrl
:网络请求的url地址
callFactory
:网络请求工厂
adapterFactories
:网络请求适配器工厂的集合
converterFactories
:数据转换器工厂的集合
callbackExecutor
:回调方法执行器
Builder(Platform platform) { this.platform = platform; // Add the built-in converter factory first. This prevents overriding its behavior but also // ensures correct behavior when using converters that consume all types. converterFactories.add(new BuiltInConverters()); }这里看出Builder设置了默认的
public Retrofit build() { if (baseUrl == null) { throw new IllegalStateException("Base URL required."); } okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } // Make a defensive copy of the adapters and add the default Call adapter. List这里就是将上述设置的变量统一配置给retrofit对象;adapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); // Make a defensive copy of the converters. List converterFactories = new ArrayList<>(this.converterFactories); return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); }
Api api=retrofit.create(Api.class);看看里面的create方法
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety. 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 serviceMethod = loadServiceMethod(method); OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } }); }看看,有木有很熟悉的感觉,没错,就是上面说的java动态代理的写法,所以我们就直接看它最重要的方法,invoke方法,在invoke方法里有最重要的三行代码;
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);return serviceMethod. callAdapter.adapt(okHttpCall) ;我们一行行的来看,首先看到的是ServiceMethod这个类,那么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; }这里有这么一句
result = new ServiceMethod.Builder(this, method).build();ServiceMethod也是通过builder模式构建的;
ServiceMethod(Builder<T> builder) { this.callFactory = builder.retrofit.callFactory(); this.callAdapter = builder.callAdapter; this.baseUrl = builder.retrofit.baseUrl(); this.responseConverter = builder.responseConverter; this.httpMethod = builder.httpMethod; this.relativeUrl = builder.relativeUrl; this.headers = builder.headers; this.contentType = builder.contentType; this.hasBody = builder.hasBody; this.isFormEncoded = builder.isFormEncoded; this.isMultipart = builder.isMultipart; this.parameterHandlers = builder.parameterHandlers; }可见主要是将一些网络请求参数传入到构造器中
public Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; this.methodAnnotations = method.getAnnotations(); this.parameterTypes = method.getGenericParameterTypes(); this.parameterAnnotationsArray = method.getParameterAnnotations(); }
builder方法中是做了一些事情的,我们知道我们先写了一个网络请求接口类,在接口里我们使用了注释来确定了一些网络请求的信息,比如是使用get方法,请求的url地址,还有方法的参数,这里的builder方法就是获取api接口中的信息。
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);这里就是通过上面构造好的ServiceMethod创建出网络请求的执行器;
第三句:
return serviceMethod.callAdapter.adapt(okHttpCall);将第二步创建的
OkHttpCall
对象传给第一步创建的
serviceMethod
对象中对应的网络请求适配器工厂的
adapt()
这里我们就可以总结一下,Retrofit.create()方法就是通过Java动态代理,获取到网络请求接口里的参数,创建出一个okhttpcall的网络请求执行器;
接下来的事情就是通过okhttpcall对象进行网络请求,这里的操作和okhttp的操作是相同的,可以参照我的上一篇博客结合来看;