博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Retrofit 源码学习与使用
阅读量:5883 次
发布时间:2019-06-19

本文共 41262 字,大约阅读时间需要 137 分钟。

预习

本文主要对retrofit的源码进行学习,了解,学习其设计模式,与实现方式。

retrofit 的基本用法:

  1. Retrofit turns your HTTP API into a Java interface.
    (将HTTP API转换为Java接口。)
public interface GitHubService {  @GET("users/{user}/repos")  Call
> listRepos(@Path("user") String user);}复制代码
  1. The Retrofit class generates an implementation of the GitHubService interface.
    (Retrofit类生成GitHubService接口的实现。)
Retrofit retrofit = new Retrofit.Builder()    .baseUrl("https://api.github.com/")    .build();GitHubService service = retrofit.create(GitHubService.class);复制代码
  1. Each Call from the created GitHubService can make a synchronous or asynchronous HTTP request to the remote webserver.
    (创建的GitHubService的每个调用都可以向远程web服务器发出同步或异步的HTTP请求。)
Call
> repos = service.listRepos("octocat");复制代码

A : service接口的构建

  1. 首先创建一个service的接口类。
  2. 指定请求方式 常见的有GET,POST,PUT,DELETE...,注意大小写。
  3. 配置请求地址,注意path的配置规则(见的7.2)
BaseUrl 和URL有关的注解中提供的值 最后结果
/post
post
  • 如果你在注解中提供的url是完整的url,则url将作为请求的url。
  • 如果你在注解中提供的url是不完整的url,且不以 / 开头,则请求的url为baseUrl+注解中提供的值
  • 如果你在注解中提供的url是不完整的url,且以 / 开头,则请求的url为baseUrl的主机部分+注解中提供的值
  1. 指定请求的回调对象,默认返回retrofit的Call<T>对象,这里我们可以
  • 通过实现retrofit的CallAdapter<R, T> 接口,来自定义我们的返回对象。
  • 再继承CallAdapter.Factory生成我们自己的Factory,在get()方法返回我们自定义的CallAdapter。
  • 最后调用Retrofit.Builder的addCallAdapterFactory(Factory)
  1. 指定请求结束后我们要接收的类型,如:okHttp返回默认的是ResponseBody,通过Retrofit的Converter可以转换为我们需要的 string 或 反序列化为java Bean对象等。
  • 定义一个MyConvert类实现retrofit的Converter接口。
  • 定义一个MyConvertFactory继承retrofit的Converter.Factory,实现responseBodyConverter()返回我们自定义的MyConvert类。
  • 使用Retrofit.Builder.addConverterFactory(new MyConvertFactory())添加我们自定义的Factory.
  1. 定义我们请求的方法名字。
  2. 请求参数的注解 见(见的第三类:参数类

  1. 请求参数的名字
  2. 参数类型
  3. 参数名称

B : retrofit的构建,源码分析

Retrofit retrofit = new Retrofit.Builder()    .baseUrl("https://api.github.com/")    .build();复制代码

我们可以看到retrofit的构建使用了builder模式。

1. 看一下Retrofit.Builder类:

/**   * Build a new {@link Retrofit}.   * 

* Calling {@link #baseUrl} is required before calling {@link #build()}. All other methods * are optional. */ public static final class Builder { private final Platform platform; private @Nullable okhttp3.Call.Factory callFactory; private HttpUrl baseUrl; private final List

converterFactories = new ArrayList<>(); private final List
adapterFactories = new ArrayList<>(); private @Nullable Executor callbackExecutor; private boolean validateEagerly; ... }复制代码

从源码可以看到:

  • 从注释看到baseUrl()必须在build()之前调用,其它可以随意。
  • platform 指定调用的平台,这里我们使用的是Android.
  • callFactory okhttp3的Call.Factory
  • baseUrl 请求的root地址
  • converterFactories 存储我们自定义的和系统默认提供的convertFactory见上面的A.5
  • adapterFactories 存储我们自定义的和系统默认提供的adapterFactory 见上面的A.4
  • callbackExecutor 线程调用类
  • validateEagerly 为true时做一些预处理操作

2. build()方法的实现

/**     * Create the {@link Retrofit} instance using the configured values.     * 

* Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link * OkHttpClient} will be created and used. */ //通过配置参数创建一个Retrofit的实例,如果没有配置HttpClient也没有配置CallFactory将采用默认的OkHttpClient public Retrofit build() { if (baseUrl == null) { // baseUrl不能为空 throw new IllegalStateException("Base URL required."); } //配置HttpClient,可以看出retrofit默认采用OkHttpClient okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } //指定callback回调方法的执行器,这里的platform是Android平台,可以看出默认下面的Android--Platform的MainThreadExecutor Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } // Make a defensive copy of the adapters and add the default Call adapter. //将我们自定义的adapterFactory添加到集合中 List

adapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); // Make a defensive copy of the converters. //将我们自定义的convertFactory添加到集合中 List
converterFactories = new ArrayList<>(this.converterFactories); // 返回Retrofit return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); }复制代码

Android--Platform

static class Android extends Platform {    @Override public Executor defaultCallbackExecutor() {      return new MainThreadExecutor();    }    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {      if (callbackExecutor == null) throw new AssertionError();      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);      }    }  }复制代码

经过build()操作后,我们配置好了一个我们想要的retrofit,接下来我们来看看这些配置是如何生效的,我们通过

GitHubService service = retrofit.create(GitHubService.class);复制代码

来生成我们service接口的实现类。我们来看create()方法。

3. retrofit.create()

public 
T create(final Class
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, @Nullable 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 = (ServiceMethod
) loadServiceMethod(method); OkHttpCall
okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } }); }复制代码
  • validateEagerly 为true时会走 eagerlyValidateMethods(service)
private void eagerlyValidateMethods(Class
service) { Platform platform = Platform.get(); for (Method method : service.getDeclaredMethods()) { if (!platform.isDefaultMethod(method)) { loadServiceMethod(method); } } } ServiceMethod
loadServiceMethod(Method method) { ServiceMethod
result = serviceMethodCache.get(method); if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = new ServiceMethod.Builder<>(this, method).build(); serviceMethodCache.put(method, result); } } return result; }复制代码

这里我们看到,是对ServiceMethod做的缓存处理。如果缓存中存在直接返回。

  • 接下来我们看见采用了动态代理的模式来创建service接口的实现类。
  • 如果是platform的方法直接return
  • 如果是我们service接口内的方法,我们看到通过上面的loadServiceMethod(method)来创建了一个ServiceMethod类,我们来看ServiceMethod类做了那些处理。

4. ServiceMethod

我们看到ServiceMethod也是采用Builder模式来构建。

/** Adapts an invocation of an interface method into an HTTP call. */final class ServiceMethod
{ // Upper and lower characters, digits, underscores, and hyphens, starting with a character. static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*"; //请求地址中{}的正则匹配表达式 static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}"); //参数名称的正常匹配 static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM); final okhttp3.Call.Factory callFactory;//okhttp3.Call.Factory final CallAdapter
callAdapter;//返回对象适配器 private final HttpUrl baseUrl;//根地址 private final Converter
responseConverter;//reponseBody转换类 private final String httpMethod;//请求方式,PUT,POST... private final String relativeUrl;//相对地址 private final Headers headers;//请求头 private final MediaType contentType;//请求的Content-Type private final boolean hasBody;//是否有请求消息体 private final boolean isFormEncoded;//是否进行参数编码 private final boolean isMultipart;// 上传时使用 private final ParameterHandler
[] parameterHandlers;//请求参数注解的封装对象 ServiceMethod(Builder
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; } ...}复制代码

接着来看 build() 方法

public ServiceMethod build() {       // [1] 创建CallAdapter,并得到返回的对象      callAdapter = createCallAdapter();      responseType = callAdapter.responseType();      ...      //[2] 创建ResponseConverte,对返回的数据进行处理      responseConverter = createResponseConverter();      //[3]遍历方法注解,获取具体的配置参数      for (Annotation annotation : methodAnnotations) {        parseMethodAnnotation(annotation);      }        ...        //[4] 方法中参数注解的处理      int parameterCount = parameterAnnotationsArray.length;      parameterHandlers = new ParameterHandler
[parameterCount]; for (int p = 0; p < parameterCount; p++) { Type parameterType = parameterTypes[p]; ... Annotation[] parameterAnnotations = parameterAnnotationsArray[p]; ... 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); }复制代码

上面的ServiceMethod.build()方法大概进行了如下操作:

  • [1] 创建CallAdapter,并得到返回的对象
  • [2] 创建ResponseConverte,对返回的数据进行处理
  • [3] 遍历方法注解,获取具体的配置参数
  • [4] 方法中参数注解的处理

接下来我们具体看看是如何实现的

[1] createCallAdapter()

private CallAdapter
createCallAdapter() { //获取方法的完整信息的返回值 Type returnType = method.getGenericReturnType(); ... //获得注解 Annotation[] annotations = method.getAnnotations(); ... return (CallAdapter
) retrofit.callAdapter(returnType, annotations); ... }复制代码

可以看到实际上是调用了retrofit.callAdapter(returnType, annotations)方法

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 = 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; } } ... }复制代码

从上面最终调用的nextCallAdapter方法,adapterFactories.get(i).get(returnType, annotations, this)看到,最终返回我们添加到adapterFactories的CallAdapterFactory.get()对象就是我们自定义的CallAdapter,注意这里是有排序概念的,排在前面的优先匹配。

再通过responseType = callAdapter.responseType();将我们自己定义的call对象,或Obserable对象,或其他需要类型返回,见上面图A.④。

[2] createResponseConverter()

private Converter
createResponseConverter() { Annotation[] annotations = method.getAnnotations(); try { return retrofit.responseBodyConverter(responseType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(e, "Unable to create converter for %s", responseType); } }复制代码

再看retrofit.responseBodyConverter(responseType, annotations)

public 
Converter
responseBodyConverter(Type type, Annotation[] annotations) { return nextResponseBodyConverter(null, type, annotations); } public
Converter
nextResponseBodyConverter( @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) { ... int start = converterFactories.indexOf(skipPast) + 1; for (int i = start, count = converterFactories.size(); i < count; i++) { Converter
converter = converterFactories.get(i).responseBodyConverter(type, annotations, this); if (converter != null) { //noinspection unchecked return (Converter
) converter; } } ... }复制代码

这里我们最终看到通过converterFactories.get(i).responseBodyConverter(type, annotations, this)方法,返回我们自定义的泛型对象见上面图A.⑤,通常是我们反序列化操作转换后的对象,或根据需要过滤一些数据,返回有用的数据。

[3] parseMethodAnnotation(annotation)

在这里处理方法上面的注解,获取到请求方式见上面图A.②,并对不同的请求方式做相应处理。

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);        if (!Void.class.equals(responseType)) {          throw methodError("HEAD method must use Void as response type.");        }      } 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("@Headers annotation is empty.");        }        headers = parseHeaders(headersToParse);      } else if (annotation instanceof Multipart) {        if (isFormEncoded) {          throw methodError("Only one encoding annotation is allowed.");        }        isMultipart = true;      } else if (annotation instanceof FormUrlEncoded) {        if (isMultipart) {          throw methodError("Only one encoding annotation is allowed.");        }        isFormEncoded = true;      }    }复制代码

接下来看一下 parseHttpMethodAndPath()

private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {      ...      this.httpMethod = httpMethod;      this.hasBody = hasBody;      if (value.isEmpty()) {        return;      }      // Get the relative URL path and existing query string, if present.      int question = value.indexOf('?');      if (question != -1 && question < value.length() - 1) {        // Ensure the query string does not have any named parameters.        String queryParams = value.substring(question + 1);        Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);        if (queryParamMatcher.find()) {          throw methodError("URL query string \"%s\" must not have replace block. "              + "For dynamic query parameters use @Query.", queryParams);        }      }      this.relativeUrl = value;      this.relativeUrlParamNames = parsePathParameters(value);    }复制代码

我们看到这里将获取到的请求方式httpMethod,是否有hasBody,还有地址路径,headers,还有地址中含有的请求参数,等等,都赋值给ServiceMethod.Builder的相应属性。

[4] parameterHandlers[]的赋值操作

在ServiceMethod.Build(Retrofit retrofit, Method method)时我们看一下

Builder(Retrofit retrofit, Method method) {      this.retrofit = retrofit;      this.method = method;      this.methodAnnotations = method.getAnnotations();      this.parameterTypes = method.getGenericParameterTypes();      this.parameterAnnotationsArray = method.getParameterAnnotations();    }复制代码
  • methodAnnotations 获得method上的所有注解
  • parameterTypes 获得所有的参数类型,String ,int ...
  • parameterAnnotationsArray 获得参数的注解集合

再看

int parameterCount = parameterAnnotationsArray.length;        //构建一个ParameterHandler集合,      parameterHandlers = new ParameterHandler
[parameterCount]; for (int p = 0; p < parameterCount; p++) { //获取第p个参数类型 Type parameterType = parameterTypes[p]; ... //获取第p个参数注解集合 Annotation[] parameterAnnotations = parameterAnnotationsArray[p]; ... //构建一个ParameterHandler对象 parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations); }复制代码

看看 parseParameter(p, parameterType, parameterAnnotations)

private ParameterHandler
parseParameter( int p, Type parameterType, Annotation[] annotations) { ParameterHandler
result = null; for (Annotation annotation : annotations) { ParameterHandler
annotationAction = parseParameterAnnotation(p, parameterType, annotations,annotation); } ... return result; } 复制代码

接着往下看parseParameterAnnotation(p, parameterType, annotations,annotation)

private ParameterHandler
parseParameterAnnotation( int p, Type type, Annotation[] annotations, Annotation annotation) { if (annotation instanceof Url) { if (gotUrl) { throw parameterError(p, "Multiple @Url method annotations found."); } if (gotPath) { throw parameterError(p, "@Path parameters may not be used with @Url."); } if (gotQuery) { throw parameterError(p, "A @Url parameter must not come after a @Query"); } if (relativeUrl != null) { throw parameterError(p, "@Url cannot be used with @%s URL", httpMethod); } gotUrl = true; if (type == HttpUrl.class || type == String.class || type == URI.class || (type instanceof Class && "android.net.Uri".equals(((Class
) type).getName()))) { return new ParameterHandler.RelativeUrl(); } else { throw parameterError(p, "@Url must be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri type."); } } else if (annotation instanceof Path) { if (gotQuery) { throw parameterError(p, "A @Path parameter must not come after a @Query."); } if (gotUrl) { throw parameterError(p, "@Path parameters may not be used with @Url."); } if (relativeUrl == null) { throw parameterError(p, "@Path can only be used with relative url on @%s", httpMethod); } gotPath = true; Path path = (Path) annotation; String name = path.value(); validatePathName(p, name); Converter
converter = retrofit.stringConverter(type, annotations); return new ParameterHandler.Path<>(name, converter, path.encoded()); } else if (annotation instanceof Query) { Query query = (Query) annotation; String name = query.value(); boolean encoded = query.encoded(); Class
rawParameterType = Utils.getRawType(type); gotQuery = true; if (Iterable.class.isAssignableFrom(rawParameterType)) { if (!(type instanceof ParameterizedType)) { throw parameterError(p, rawParameterType.getSimpleName() + " must include generic type (e.g., " + rawParameterType.getSimpleName() + "
)"); } ParameterizedType parameterizedType = (ParameterizedType) type; Type iterableType = Utils.getParameterUpperBound(0, parameterizedType); Converter
converter = retrofit.stringConverter(iterableType, annotations); return new ParameterHandler.Query<>(name, converter, encoded).iterable(); } else if (rawParameterType.isArray()) { Class
arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType()); Converter
converter = retrofit.stringConverter(arrayComponentType, annotations); return new ParameterHandler.Query<>(name, converter, encoded).array(); } else { Converter
converter = retrofit.stringConverter(type, annotations); return new ParameterHandler.Query<>(name, converter, encoded); } } else if (annotation instanceof QueryName) { QueryName query = (QueryName) annotation; boolean encoded = query.encoded(); Class
rawParameterType = Utils.getRawType(type); gotQuery = true; if (Iterable.class.isAssignableFrom(rawParameterType)) { if (!(type instanceof ParameterizedType)) { throw parameterError(p, rawParameterType.getSimpleName() + " must include generic type (e.g., " + rawParameterType.getSimpleName() + "
)"); } ParameterizedType parameterizedType = (ParameterizedType) type; Type iterableType = Utils.getParameterUpperBound(0, parameterizedType); Converter
converter = retrofit.stringConverter(iterableType, annotations); return new ParameterHandler.QueryName<>(converter, encoded).iterable(); } else if (rawParameterType.isArray()) { Class
arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType()); Converter
converter = retrofit.stringConverter(arrayComponentType, annotations); return new ParameterHandler.QueryName<>(converter, encoded).array(); } else { Converter
converter = retrofit.stringConverter(type, annotations); return new ParameterHandler.QueryName<>(converter, encoded); } } else if (annotation instanceof QueryMap) { Class
rawParameterType = Utils.getRawType(type); if (!Map.class.isAssignableFrom(rawParameterType)) { throw parameterError(p, "@QueryMap parameter type must be Map."); } Type mapType = Utils.getSupertype(type, rawParameterType, Map.class); if (!(mapType instanceof ParameterizedType)) { throw parameterError(p, "Map must include generic types (e.g., Map
)"); } ParameterizedType parameterizedType = (ParameterizedType) mapType; Type keyType = Utils.getParameterUpperBound(0, parameterizedType); if (String.class != keyType) { throw parameterError(p, "@QueryMap keys must be of type String: " + keyType); } Type valueType = Utils.getParameterUpperBound(1, parameterizedType); Converter
valueConverter = retrofit.stringConverter(valueType, annotations); return new ParameterHandler.QueryMap<>(valueConverter, ((QueryMap) annotation).encoded()); } else if (annotation instanceof Header) { Header header = (Header) annotation; String name = header.value(); Class
rawParameterType = Utils.getRawType(type); if (Iterable.class.isAssignableFrom(rawParameterType)) { if (!(type instanceof ParameterizedType)) { throw parameterError(p, rawParameterType.getSimpleName() + " must include generic type (e.g., " + rawParameterType.getSimpleName() + "
)"); } ParameterizedType parameterizedType = (ParameterizedType) type; Type iterableType = Utils.getParameterUpperBound(0, parameterizedType); Converter
converter = retrofit.stringConverter(iterableType, annotations); return new ParameterHandler.Header<>(name, converter).iterable(); } else if (rawParameterType.isArray()) { Class
arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType()); Converter
converter = retrofit.stringConverter(arrayComponentType, annotations); return new ParameterHandler.Header<>(name, converter).array(); } else { Converter
converter = retrofit.stringConverter(type, annotations); return new ParameterHandler.Header<>(name, converter); } } else if (annotation instanceof HeaderMap) { Class
rawParameterType = Utils.getRawType(type); if (!Map.class.isAssignableFrom(rawParameterType)) { throw parameterError(p, "@HeaderMap parameter type must be Map."); } Type mapType = Utils.getSupertype(type, rawParameterType, Map.class); if (!(mapType instanceof ParameterizedType)) { throw parameterError(p, "Map must include generic types (e.g., Map
)"); } ParameterizedType parameterizedType = (ParameterizedType) mapType; Type keyType = Utils.getParameterUpperBound(0, parameterizedType); if (String.class != keyType) { throw parameterError(p, "@HeaderMap keys must be of type String: " + keyType); } Type valueType = Utils.getParameterUpperBound(1, parameterizedType); Converter
valueConverter = retrofit.stringConverter(valueType, annotations); return new ParameterHandler.HeaderMap<>(valueConverter); } else if (annotation instanceof Field) { if (!isFormEncoded) { throw parameterError(p, "@Field parameters can only be used with form encoding."); } Field field = (Field) annotation; String name = field.value(); boolean encoded = field.encoded(); gotField = true; Class
rawParameterType = Utils.getRawType(type); if (Iterable.class.isAssignableFrom(rawParameterType)) { if (!(type instanceof ParameterizedType)) { throw parameterError(p, rawParameterType.getSimpleName() + " must include generic type (e.g., " + rawParameterType.getSimpleName() + "
)"); } ParameterizedType parameterizedType = (ParameterizedType) type; Type iterableType = Utils.getParameterUpperBound(0, parameterizedType); Converter
converter = retrofit.stringConverter(iterableType, annotations); return new ParameterHandler.Field<>(name, converter, encoded).iterable(); } else if (rawParameterType.isArray()) { Class
arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType()); Converter
converter = retrofit.stringConverter(arrayComponentType, annotations); return new ParameterHandler.Field<>(name, converter, encoded).array(); } else { Converter
converter = retrofit.stringConverter(type, annotations); return new ParameterHandler.Field<>(name, converter, encoded); } } else if (annotation instanceof FieldMap) { if (!isFormEncoded) { throw parameterError(p, "@FieldMap parameters can only be used with form encoding."); } Class
rawParameterType = Utils.getRawType(type); if (!Map.class.isAssignableFrom(rawParameterType)) { throw parameterError(p, "@FieldMap parameter type must be Map."); } Type mapType = Utils.getSupertype(type, rawParameterType, Map.class); if (!(mapType instanceof ParameterizedType)) { throw parameterError(p, "Map must include generic types (e.g., Map
)"); } ParameterizedType parameterizedType = (ParameterizedType) mapType; Type keyType = Utils.getParameterUpperBound(0, parameterizedType); if (String.class != keyType) { throw parameterError(p, "@FieldMap keys must be of type String: " + keyType); } Type valueType = Utils.getParameterUpperBound(1, parameterizedType); Converter
valueConverter = retrofit.stringConverter(valueType, annotations); gotField = true; return new ParameterHandler.FieldMap<>(valueConverter, ((FieldMap) annotation).encoded()); } else if (annotation instanceof Part) { if (!isMultipart) { throw parameterError(p, "@Part parameters can only be used with multipart encoding."); } Part part = (Part) annotation; gotPart = true; String partName = part.value(); Class
rawParameterType = Utils.getRawType(type); if (partName.isEmpty()) { if (Iterable.class.isAssignableFrom(rawParameterType)) { if (!(type instanceof ParameterizedType)) { throw parameterError(p, rawParameterType.getSimpleName() + " must include generic type (e.g., " + rawParameterType.getSimpleName() + "
)"); } ParameterizedType parameterizedType = (ParameterizedType) type; Type iterableType = Utils.getParameterUpperBound(0, parameterizedType); if (!MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(iterableType))) { throw parameterError(p, "@Part annotation must supply a name or use MultipartBody.Part parameter type."); } return ParameterHandler.RawPart.INSTANCE.iterable(); } else if (rawParameterType.isArray()) { Class
arrayComponentType = rawParameterType.getComponentType(); if (!MultipartBody.Part.class.isAssignableFrom(arrayComponentType)) { throw parameterError(p, "@Part annotation must supply a name or use MultipartBody.Part parameter type."); } return ParameterHandler.RawPart.INSTANCE.array(); } else if (MultipartBody.Part.class.isAssignableFrom(rawParameterType)) { return ParameterHandler.RawPart.INSTANCE; } else { throw parameterError(p, "@Part annotation must supply a name or use MultipartBody.Part parameter type."); } } else { Headers headers = Headers.of("Content-Disposition", "form-data; name=\"" + partName + "\"", "Content-Transfer-Encoding", part.encoding()); if (Iterable.class.isAssignableFrom(rawParameterType)) { if (!(type instanceof ParameterizedType)) { throw parameterError(p, rawParameterType.getSimpleName() + " must include generic type (e.g., " + rawParameterType.getSimpleName() + "
)"); } ParameterizedType parameterizedType = (ParameterizedType) type; Type iterableType = Utils.getParameterUpperBound(0, parameterizedType); if (MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(iterableType))) { throw parameterError(p, "@Part parameters using the MultipartBody.Part must not " + "include a part name in the annotation."); } Converter
converter = retrofit.requestBodyConverter(iterableType, annotations, methodAnnotations); return new ParameterHandler.Part<>(headers, converter).iterable(); } else if (rawParameterType.isArray()) { Class
arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType()); if (MultipartBody.Part.class.isAssignableFrom(arrayComponentType)) { throw parameterError(p, "@Part parameters using the MultipartBody.Part must not " + "include a part name in the annotation."); } Converter
converter = retrofit.requestBodyConverter(arrayComponentType, annotations, methodAnnotations); return new ParameterHandler.Part<>(headers, converter).array(); } else if (MultipartBody.Part.class.isAssignableFrom(rawParameterType)) { throw parameterError(p, "@Part parameters using the MultipartBody.Part must not " + "include a part name in the annotation."); } else { Converter
converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations); return new ParameterHandler.Part<>(headers, converter); } } } else if (annotation instanceof PartMap) { if (!isMultipart) { throw parameterError(p, "@PartMap parameters can only be used with multipart encoding."); } gotPart = true; Class
rawParameterType = Utils.getRawType(type); if (!Map.class.isAssignableFrom(rawParameterType)) { throw parameterError(p, "@PartMap parameter type must be Map."); } Type mapType = Utils.getSupertype(type, rawParameterType, Map.class); if (!(mapType instanceof ParameterizedType)) { throw parameterError(p, "Map must include generic types (e.g., Map
)"); } ParameterizedType parameterizedType = (ParameterizedType) mapType; Type keyType = Utils.getParameterUpperBound(0, parameterizedType); if (String.class != keyType) { throw parameterError(p, "@PartMap keys must be of type String: " + keyType); } Type valueType = Utils.getParameterUpperBound(1, parameterizedType); if (MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(valueType))) { throw parameterError(p, "@PartMap values cannot be MultipartBody.Part. " + "Use @Part List
or a different value type instead."); } Converter
valueConverter = retrofit.requestBodyConverter(valueType, annotations, methodAnnotations); PartMap partMap = (PartMap) annotation; return new ParameterHandler.PartMap<>(valueConverter, partMap.encoding()); } else if (annotation instanceof Body) { if (isFormEncoded || isMultipart) { throw parameterError(p, "@Body parameters cannot be used with form or multi-part encoding."); } if (gotBody) { throw parameterError(p, "Multiple @Body method annotations found."); } Converter
converter; try { converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw parameterError(e, p, "Unable to create @Body converter for %s", type); } gotBody = true; return new ParameterHandler.Body<>(converter); } return null; // Not a Retrofit annotation. }复制代码

这么超长的代码,将我们方法参数的注解,参数类型,参数值都拿到,封装为 ParameterHandler 并保存到ParameterHandler<?>[] parameterHandlers集合。

至此,我们将我们创建的service接口所调用方法中的请求方式,请求路径,返回值,请求参数等都获取到了,并存储到一个ServiceMethod对象中。

接下来我们再回到 retrofit.Create()

public 
T create(final Class
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, @Nullable Object[] args) throws Throwable { ... //这里最终返回到Retrofit中的ServiceMethod
,来存储我们构建的serviceMethod ServiceMethod
serviceMethod = (ServiceMethod
) loadServiceMethod(method); //再看OkHttpCall OkHttpCall
okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } }); }复制代码

5. OkHttpCall<Object>

将我们上面构建的serviceMethod 与参数传进来

OkHttpCall(ServiceMethod
serviceMethod, @Nullable Object[] args) { this.serviceMethod = serviceMethod; this.args = args; }复制代码

最后通过serviceMethod.callAdapter.adapt(okHttpCall)就创建好了我们service的一个实现类。

再看看**callAdapter.adapt(okHttpCall)**这里的callAdapter是们自定义的callAdapter对象,Android默认的是Call<>;若设置了RxJavaCallAdapterFactory,返回的则是Observable<>,这里我们看看后一种情况下的实现方式。

RxJavaCallAdapterFactory-->RxJava2CallAdapter 这里我们看RxJava2CallAdapter的adapt()方法。

@Override public Object adapt(Call
call) { Observable
> responseObservable = isAsync ? new CallEnqueueObservable<>(call) : new CallExecuteObservable<>(call); Observable
observable; if (isResult) { observable = new ResultObservable<>(responseObservable); } else if (isBody) { observable = new BodyObservable<>(responseObservable); } else { observable = responseObservable; } if (scheduler != null) { observable = observable.subscribeOn(scheduler); } if (isFlowable) { return observable.toFlowable(BackpressureStrategy.LATEST); } if (isSingle) { return observable.singleOrError(); } if (isMaybe) { return observable.singleElement(); } if (isCompletable) { return observable.ignoreElements(); } return observable; }复制代码

我们看到但isAsync是异步情况下时,new CallEnqueueObservable<>(call),创建了一个CallEnqueueObservable 对象,并将retrofit的okhttpCall继续传进来.

我们知道在RxJava,Observable的subscribe()触发了代码执行的操作。来看:

@SchedulerSupport(SchedulerSupport.NONE)    @Override    public final void subscribe(Observer
observer) { ... @Override public void enqueue(final Callback
callback) { checkNotNull(callback, "callback == null");//这里创建一个okhttp3.Call的call对象 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 { //这里看到通过createRawCall() 创建返回了一个call call = rawCall = createRawCall(); } catch (Throwable t) { failure = creationFailure = t; } } } if (failure != null) { callback.onFailure(this, failure); return; } if (canceled) { call.cancel(); }//实际上就是通过okhttp3.call来请求 call.enqueue(new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) throws IOException { Response
response; try { response = parseResponse(rawResponse); } catch (Throwable e) { callFailure(e); return; } callSuccess(response); } @Override public void onFailure(okhttp3.Call call, IOException e) { callback.onFailure(OkHttpCall.this, e); } private void callFailure(Throwable e) { callback.onFailure(OkHttpCall.this, e); } private void callSuccess(Response
response) { callback.onResponse(OkHttpCall.this, response); ... } }复制代码

createRawCall()

private okhttp3.Call createRawCall() throws IOException {[1] 创建一个request 请求对象    Request request = serviceMethod.toRequest(args);    [2]调用newCall(request)返回一个okhttp3.Call     okhttp3.Call call = serviceMethod.callFactory.newCall(request);    if (call == null) {      throw new NullPointerException("Call.Factory returned null.");    }    return call;  }复制代码

serviceMethod.toRequest(args)

Request toRequest(@Nullable Object... args) throws IOException {  //这里new了一个requestBuilder 将我们获取到的请求的相关信息传进去    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,        contentType, hasBody, isFormEncoded, isMultipart);    //参数值解析    ParameterHandler[] handlers = (ParameterHandler[]) parameterHandlers;        ...    for (int p = 0; p < argumentCount; p++) {      handlers[p].apply(requestBuilder, args[p]);    }//这里调用build()     return requestBuilder.build();  }复制代码

下面看一下requestBuilder.build() 是如何创建一个request对象的

Request build() {    HttpUrl url;    HttpUrl.Builder urlBuilder = this.urlBuilder;    if (urlBuilder != null) {      url = urlBuilder.build();    } else {      // No query parameters triggered builder creation, just combine the relative URL and base URL.      //noinspection ConstantConditions Non-null if urlBuilder is null.      url = baseUrl.resolve(relativeUrl);      if (url == null) {        throw new IllegalArgumentException(            "Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl);      }    }    RequestBody body = this.body;    if (body == null) {      // Try to pull from one of the builders.      if (formBuilder != null) {        body = formBuilder.build();      } else if (multipartBuilder != null) {        body = multipartBuilder.build();      } else if (hasBody) {        // Body is absent, make an empty body.        body = RequestBody.create(null, new byte[0]);      }    }    MediaType contentType = this.contentType;    if (contentType != null) {      if (body != null) {        body = new ContentTypeOverridingRequestBody(body, contentType);      } else {        requestBuilder.addHeader("Content-Type", contentType.toString());      }    }    return requestBuilder        .url(url)        .method(method, body)        .build();  }复制代码

接着看看call.enqueue()

@Override public void enqueue(Callback responseCallback) {    synchronized (this) {      if (executed) throw new IllegalStateException("Already Executed");      executed = true;    }    captureCallStackTrace();    eventListener.callStart(this);    client.dispatcher().enqueue(new AsyncCall(responseCallback));  }复制代码

client.dispatcher().enqueue(new AsyncCall(responseCallback));

synchronized void enqueue(AsyncCall call) {    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {          runningAsyncCalls.add(call);      //可以看到这里执行了网络请求,并通过call完成返回请求结果的回调。      executorService().execute(call);    } else {      readyAsyncCalls.add(call);    }  }复制代码

从上面可以看到,这里最终是通过创建一个okHttp3.Call对象,构建出一个网络请求的Request,发送网络请求,并调用了call.enqueue()最后将请求到的结果,返回到Retrofit的Callback对象。

package retrofit2;public interface Callback
{ void onResponse(Call
call, Response
response); void onFailure(Call
call, Throwable t);复制代码

到这里一个请求就结束了。

总结

梳理一下整个过程:

  1. 书写我们的service请求接口,配置好请求路径,请求方式,参数配置等。
  2. 构建我们自定义的convert ,convertAdapter 。
  3. 构建retrofit对象,并添加我们的convertFactory,converAdapterFactory等。
  4. 通过retrofit的create()动态代理实现service接口的实现类
  5. 解析 网络请求接口的注解 配置 网络请求参数
  6. 通过 网络请求适配器 将 网络请求对象 进行平台适配
  7. 通过 网络请求执行器 发送网络请求
  8. 通过 数据转换器 解析服务器返回的数据
  9. 通过 回调执行器 切换线程(子线程 ->>主线程)
  10. 最后用户在主线程处理返回结果

参考文章

(参考使用了下面文章的部分内容与资源)

转载于:https://juejin.im/post/5b2c91cb51882574b55e5ae0

你可能感兴趣的文章
memcached 分布式聚类算法
查看>>
jquery css3问卷答题卡翻页动画效果
查看>>
$digest already in progress 解决办法——续
查看>>
虚拟机 centos设置代理上网
查看>>
Struts2中Date日期转换的问题
查看>>
mysql 数据类型
查看>>
Ubuntu 设置当前用户sudo免密码
查看>>
设置tomcat远程debug
查看>>
android 电池(一):锂电池基本原理篇【转】
查看>>
Total Command 常用快捷键
查看>>
ionic 调用手机的打电话功能
查看>>
怎么使用阿里云直播服务应用到现在主流直播平台中
查看>>
1000 加密算法
查看>>
exif_imagetype() 函数在linux下的php中不存在
查看>>
Ruby的case语句
查看>>
Linux的链接文件-ln命令
查看>>
maven的tomcat插件如何进行debug调试
查看>>
table表头固定
查看>>
截取字符串中两个字符串中的字符串
查看>>
spring xml properties split with comma for list
查看>>