首先附上《Retrofit2源码解析》原文链接:http://bxbxbai.github.io/2015/12/13/retrofit2/
基于《Retrofit2源码解析》,本文主要在retrofit更新到2.1版本后,其中源码稍有改动的地方做了一些补充,并以《Retrofit2源码解析》的文章结构重新梳理了Retrofit的相关知识以及对于使用时的注解介绍。
本文只是retrofit2.0与2.1版本中的区别介绍,顺便将自己看源码时本人理解的代码注释记录一下,作为学习心得。
一、Retrofit是什么
A type-safe HTTP client for Android and Java.
它是一个HTTP请求工具
二、Retrofit怎么用
链接:http://bxbxbai.github.io/2015/12/13/retrofit2/
本人觉得上述文章关于如何简单使用retrofit的内容简单易懂,各位读者可以直接看,本文就不多说重复的内容了。下面主要列举一些开发中常用到的请求方式的写法。
三、Retrofit请求方式注解类型
- 简单的GET、POST请求

- 添加参数(header)请求

- 表单类型的请求

- Multipart(文件上传)类型的请求

- 文件下载

四、Retrofit原理
1 2 3 4
| Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL) .addConverterFactory(GsonConverterFactory.create()) .build();
|
1.这是创建retrofit对象的方法,我们就进去build()方法中一看究竟。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 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<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); // Make a defensive copy of the converters. List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories); return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); }
|
build()方法中,做了这几件事情:
1.创建OKHttpClient
2.创建callBackExecutor
3.创建List
4.创建List
5.调用Retrofit的构造方法,创建Retrofit对象
1
| WeatherService service = weatherRetrofit.create(WeatherService.class);
|
2.调用retrofit对象的create()方法,创建一个动态代理的对象(“服务”的接口)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public <T> T create(final Class<T> service) { Utils.validateServiceInterface(service);//验证外部传进的“服务”接口是否合法 if (validateEagerly) {//根据validateEagerly判断是否对接口中的全部方法进行缓存 eagerlyValidateMethods(service); } //使用Proxy工厂类返回一个泛型实例。 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);//java8出现default修饰符,这里retrofit就直接invoke default method } ServiceMethod serviceMethod = loadServiceMethod(method);//加载调用的方法 OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);//将方法中的参数和调用方法构建出一个OKHttpCall return serviceMethod.callAdapter.adapt(okHttpCall);//将构建好的OKHttpCall通过serviceMethod中的CallAdapter发送出去 } }); } ``` ```python //加载方法,可以看出将传进来的method放在了LinkMap中进行缓存,取得时候先从缓存中取 ServiceMethod loadServiceMethod(Method method) { ServiceMethod result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = new ServiceMethod.Builder(this, method).build();//创建ServiceMethod,进去build()方法中去看看 serviceMethodCache.put(method, result); } } return result; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| //首先创建了callAdapter public ServiceMethod build() { callAdapter = createCallAdapter(); responseType = callAdapter.responseType(); if (responseType == Response.class || responseType == okhttp3.Response.class) { throw methodError("'" + Utils.getRawType(responseType).getName() + "' is not a valid response body type. Did you mean ResponseBody?"); } //创建responseConverter responseConverter = createResponseConverter(); //循环遍历方法中的注解,进行解析 for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } //如果缺少请求方式的注解,则抛出error if (httpMethod == null) { throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.)."); } //以下代码就不一一翻译了。。。 if (!hasBody) { if (isMultipart) { throw methodError( "Multipart can only be specified on HTTP methods with request body (e.g., @POST)."); } if (isFormEncoded) { throw methodError("FormUrlEncoded can only be specified on HTTP methods with " + "request body (e.g., @POST)."); } } //以下代码功能是获取参数的个数,进行遍历,判断参数的注解类型是否规范,不规范抛出error,将参数根据注解类型进行解析。 int parameterCount = parameterAnnotationsArray.length; parameterHandlers = new ParameterHandler<?>[parameterCount]; for (int p = 0; p < parameterCount; p++) { Type parameterType = parameterTypes[p]; if (Utils.hasUnresolvableType(parameterType)) { throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s", parameterType); } Annotation[] parameterAnnotations = parameterAnnotationsArray[p]; if (parameterAnnotations == null) { throw parameterError(p, "No Retrofit annotation found."); } parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations); } if (relativeUrl == null && !gotUrl) { throw methodError("Missing either @%s URL or @Url parameter.", httpMethod); } if (!isFormEncoded && !isMultipart && !hasBody && gotBody) { throw methodError("Non-body HTTP method cannot contain @Body."); } if (isFormEncoded && !gotField) { throw methodError("Form-encoded method must contain at least one @Field."); } if (isMultipart && !gotPart) { throw methodError("Multipart method must contain at least one @Part."); } return new ServiceMethod<>(this); }
|
createCallAdapter()这个方法中,跟进源代码中可以看到:
1 2 3 4 5 6 7 8 9 10 11 12
| public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { …… int start = adapterFactories.indexOf(skipPast) + 1; for (int i = start, count = adapterFactories.size(); i < count; i++) { CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this); if (adapter != null) { return adapter; } } …… }
|
3.CallAdapter的作用,就是将Call对象转化为另一个对象,可能是为了支持RxJava才设计这个类。
createResponseConverter()这个方法中,创建了Converter< F,T >,跟进源码中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast, Type type, Annotation[] annotations) { …… int start = converterFactories.indexOf(skipPast) + 1; for (int i = start, count = converterFactories.size(); i < count; i++) { Converter<ResponseBody, ?> converter = converterFactories.get(i).responseBodyConverter(type, annotations, this); if (converter != null) { //noinspection unchecked return (Converter<ResponseBody, T>) converter; } } …… }
|
4.这个接口主要的作用就是将HTTP返回的数据解析成Java对象,主要由Xml、Gson、protobuf等等,你可以在创建Retrofit对象时添加你需要使用的Converter实现。
1
| Call<CityListBean> call = service.listCity("北京");
|
刚才通过create创建的动态代理对象,当执行listCity时,将会返回一个OKHttpCall对象(从源码中可以看到Retrofit默认使用OKHttpCall),根据这个Call对象才能开始执行Http请求。
1 2 3 4 5 6 7 8
| call.enqueue(new Callback<CityListBean>() { @Override public void onResponse(Call<CityListBean> call, Response<CityListBean> response) { } @Override public void onFailure(Call<CityListBean> call, Throwable t) { } });
|
或者
1
| Response<BaseBean> response = baseBeanCall.execute();
|
执行请求方法有两种,前者是异步请求,后者是同步请求。进入enqueue方法中一看究竟:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| @Override public void enqueue(final Callback<T> callback) { if (callback == null) throw new NullPointerException("callback == null"); 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 { call = rawCall = createRawCall(); } catch (Throwable t) { failure = creationFailure = t; } } } if (failure != null) { callback.onFailure(this, failure); return; } if (canceled) { call.cancel(); } call.enqueue(new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) throws IOException { Response<T> response; try { response = parseResponse(rawResponse); } catch (Throwable e) { callFailure(e); return; } callSuccess(response); } @Override public void onFailure(okhttp3.Call call, IOException e) { try { callback.onFailure(OkHttpCall.this, e); } catch (Throwable t) { t.printStackTrace(); } } private void callFailure(Throwable e) { try { callback.onFailure(OkHttpCall.this, e); } catch (Throwable t) { t.printStackTrace(); } } private void callSuccess(Response<T> response) { try { callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { t.printStackTrace(); } } }); }
|
从源码中可以看出,enqueue中实际的网络请求操作是使用OKHttp中得Dispatcher.enqueue(),(往下的源码跟进就不属于本文中得范畴,读者有兴趣可以看看OKHttp的源码),请求返回的数据,通过CallBack返回给调用者。
5.CallBack这个接口中只有两个方法:
void onResponse(Call call, Response response);
void onFailure(Call call, Throwable t);
五、结束语
至此,Retrofit的源码分析到这就结束了,感谢本文多次提到的《Retrofit2源码解析》的作者,让我在分析源码的过程中屡屡受益!本文内容均是个人对源码的理解,在表述上可能存在缺陷,请各位读者多多提出宝贵建议。