Retrofit算下出现的时间也已经好几年了,为什么今天还要做这篇解析呢?早先出去面试时其实有被问到实现原理,鉴于当时的理解只是说了基于注解实现,没有真的翻阅源码,回答肯定不能令别人满意,所以就没有接着往下聊了。
最近回想过来, 翻看了下Retrofit源码;所以写下这篇做下记录…
Retrofit是什么
理解上就是一个网络库,基于okhttp包装;提供了一些简洁的api调用方式进行restful api请求。
学到什么
加深Retrofit库的使用,针对一些使用场景可以帮助理解
代理;静态、动态代理,很典型的一个代理实现
注解
以及运用到的一些设计模式等
概览
看下Retrofit的简单使用:
1 2 3 4 5 public interface RequestService { @GET ("/xxxx/xxxx" ) Call<ResultData> sendRequest () ; }
1 2 3 4 5 Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://www.baidu.com" ) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 RequestService service = retrofit.create(RequestService.class); Call<ResultData> call = service.sendRequest(); call.enqueue(new Callback<ResultData>() { @Override public void onResponse (Call<ResultData> call, Response<ResultData> response) { } @Override public void onFailure (Call<ResultData> call, Throwable throwable) { } }); Response<ResultData> response = call.execute();
通过上述步骤后,我们就完成了一个实质性的网络请求;是不是很简单也很简洁;我们看下这过程中涉及到的一些模块,上一下图:
interface service:定义了请求的基本信息;请求地址、参数、header等,都是通过注解形式进行定义,这边涉及到的注解就不一一展开说明了, 有兴趣的同学可以自己翻看源码或是官网 进行了解
CallAdapter、ConverterAdapter: Retrofit通过解析service上method的请求方法上的注解,再根据情况适配请求,CallAdapter做的就是这么个事;而ConvertAdapter则通过适配返回数据进行数据响应的解析。
Call、Obserable:为了更好的适配我们项目中使用到的技术栈,callAdapter中会根据service中method返回类型进行适配,这样我们就可以很方便的结合我们自身需求需要的网络发起方式来实现了。所以这就是我要call方式请求方式则是call方式、要rx方式则是rx方式(简单理解适配器模式)。
源码解析
入口方法,直接是一个动态代理实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public <T> T create (final Class<T> service) { validateServiceInterface(service); return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { private final Platform platform = Platform.get(); private final Object[] emptyArgs = new Object[0 ]; @Override public @Nullable Object invoke (Object proxy, Method method, @Nullable Object[] args) throws Throwable { if (method.getDeclaringClass() == Object.class) { return method.invoke(this , args); } if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } }); }
创建前的合法性校验;不支持非接口类型service、不支持泛型参数等
根据平台特性处理;其实这边我们应该主要关注Android平台就行了。
最终loadServiceMethod(method).invoke(args != null ? args : emptyArgs);实现代理方法
如上图,整个流程是根据接口Service创建代理Proxy Serivce,最终调用Proxy Service返回值进行请求发起。
接下来我们看下怎么loadServiceMethod的
1 2 3 4 5 6 7 8 9 10 11 12 13 ServiceMethod<?> loadServiceMethod(Method method) { ServiceMethod<?> result = serviceMethodCache.get(method); if (result != null ) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null ) { result = ServiceMethod.parseAnnotations(this , method); serviceMethodCache.put(method, result); } } return result; }
常规操作;先缓存取值,没有则创建,继续看下ServiceMethod.parseAnnotations方法是如何创建的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 static <T> ServiceMethod<T> parseAnnotations (Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); Type returnType = method.getGenericReturnType(); if (Utils.hasUnresolvableType(returnType)) { throw methodError(method, "Method return type must not include a type variable or wildcard: %s" , returnType); } if (returnType == void .class) { throw methodError(method, "Service methods cannot return void." ); } return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); }
这边可以注意到RequestFactory.parseAnnotations其实就是对请求注解进行解析,看下实现
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 private void parseMethodAnnotation (Annotation annotation) { if (annotation instanceof DELETE) { parseHttpMethodAndPath("DELETE" , ((DELETE) annotation).value(), false ); } else if (annotation instanceof GET) { parseHttpMethodAndPath("GET" , ((GET) annotation).value(), false ); } else if (annotation instanceof HEAD) { parseHttpMethodAndPath("HEAD" , ((HEAD) annotation).value(), false ); } else if (annotation instanceof PATCH) { parseHttpMethodAndPath("PATCH" , ((PATCH) annotation).value(), true ); } else if (annotation instanceof POST) { parseHttpMethodAndPath("POST" , ((POST) annotation).value(), true ); } else if (annotation instanceof PUT) { parseHttpMethodAndPath("PUT" , ((PUT) annotation).value(), true ); } else if (annotation instanceof OPTIONS) { parseHttpMethodAndPath("OPTIONS" , ((OPTIONS) annotation).value(), false ); } else if (annotation instanceof HTTP) { HTTP http = (HTTP) annotation; parseHttpMethodAndPath(http.method(), http.path(), http.hasBody()); } else if (annotation instanceof retrofit2.http.Headers) { String[] headersToParse = ((retrofit2.http.Headers) annotation).value(); if (headersToParse.length == 0 ) { throw methodError(method, "@Headers annotation is empty." ); } headers = parseHeaders(headersToParse); } else if (annotation instanceof Multipart) { if (isFormEncoded) { throw methodError(method, "Only one encoding annotation is allowed." ); } isMultipart = true ; } else if (annotation instanceof FormUrlEncoded) { if (isMultipart) { throw methodError(method, "Only one encoding annotation is allowed." ); } isFormEncoded = true ; } }
这不就是我们使用Retrofit时用到的注解么…,我们继续跟进看下HttpServiceMethod.parseAnnotations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations ( Retrofit retrofit, Method method, RequestFactory requestFactory) { CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations); Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType); okhttp3.Call.Factory callFactory = retrofit.callFactory; if (!isKotlinSuspendFunction) { return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter); } else if (continuationWantsResponse) { return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter); } else { return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter, continuationBodyNullable); } }
可以看到这边进行了callAdapter和responseConverter的包装;看下callAdapter实现
1 2 3 4 5 6 7 8 9 private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter ( Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) { try { return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations); } catch (RuntimeException e) { throw methodError(method, e, "Unable to create call adapter for %s" , returnType); } }
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 public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { return nextCallAdapter(null , returnType, annotations); } public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { int start = callAdapterFactories.indexOf(skipPast) + 1 ; for (int i = start, count = callAdapterFactories.size(); i < count; i++) { CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this ); if (adapter != null ) { return adapter; } } }
最终路由到Retrofit的callAdapterFactories进行适配得到匹配的call,responseConverter同理。再在最后返回由这匹配到的call、response包装的HttpServiceMethod,在调用proxyService的方法访问时回调这个HttpServiceMethod的invoke方法。也就是Retrofit类中一开始create方法中的loadServiceMethod(method).invoke(args != null ? args : emptyArgs)。
最后
代码实现思路清晰,阅读食用起来很顺。扩展性方面也是很友好的,在代码中已经看到了对kotlin的支持,基本已经感知不到okhttp相关部分。