美文网首页
Retrofit源码解析

Retrofit源码解析

作者: Android程序员老鸦 | 来源:发表于2021-07-17 20:51 被阅读0次

Retrofit是一套基于okhttp来封装的网络框架,它的意义在于将okhttp的使用变得更简洁更解耦,其作者JakeWharton是大名鼎鼎的Android开发巨人,ButterKnife,picasso,okhttp,okio等神级项目皆出自他手,所以Retrofit的源码还是很有学习价值的。
废话不多说,先来导入项目依赖:

    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.3.0'

创建一个接口类ServerApi ,先只写一个方法getUserInfo():

public interface ServerApi {
    @GET("getInfo")
    Call<Result<UserInfo>> getUserInfo();
}

在activity里使用Retrofit来访问接口:

       Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://192.168.8.169:8080/OkHttpServer/")//host
                .addConverterFactory(GsonConverterFactory.create())//解析转换工厂
                .client(new OkHttpClient())//传入OkHttpClient对象
                .build();
        ServerApi serverApi = retrofit.create(ServerApi.class);//得到ServerApi 的具体实现类对象
        Call<Result<UserInfo>> userInfoCall = serverApi.getUserInfo();//得到call
        //调用异步方法
        userInfoCall.enqueue(new Callback<Result<UserInfo>>() {
            @Override
            public void onResponse(Call<Result<UserInfo>> call, Response<Result<UserInfo>> response) {

            }

            @Override
            public void onFailure(Call<Result<UserInfo>> call, Throwable t) {

            }
        });

再重申一下,Retrofit是对okhttp的一个封装, 所以它的核心代码不是网络访问,而是抽离业务代码和功能代码 ,我们看看他是怎么做的。
上面的代码一看就知道关键在于那个create()方法,它把一个接口类变成了一个实例对象:

 public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
  //重点在这里,利用jdk动态代理返回了接口的实现类对象,动态代理可以单独写一篇文章来研究
  //这里只需要知道,接口里的每个方法会执行里面的invoke()方法回调
    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.
            //如果是object顶级类的方法就直接执行
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            //是平台的方法也直接执行
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            //这里是解析method的重要方法,主要是各种注解的解析
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            //得到一个OkHttpCall,算是okhttp里的realCall
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //callAdapter如果添加了rxjava的会返回一个observable
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

看看loadServiceMethod()方法:

//这个方法的目的是为了获取ServiceMethod,这个对象封装了这个网络请求方法构建okhttp请求的所有参数
ServiceMethod<?, ?> loadServiceMethod(Method method) {
    //一看就是个缓存啦,有就返回缓存的
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;
  
    synchronized (serviceMethodCache) {
      //同步代码里又判断了一次缓存
      result = serviceMethodCache.get(method);
      if (result == null) {
        //新建了一个ServiceMethod,把retrofit和method传进去了
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

来看看ServiceMethod的主要代码:

final class ServiceMethod<R, T> {
  // 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;
  final CallAdapter<R, T> callAdapter;

  private final HttpUrl baseUrl;
  private final Converter<ResponseBody, R> responseConverter;
  private final String httpMethod;
  private final String relativeUrl;
  private final Headers headers;
  private final MediaType contentType;
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
  private final ParameterHandler<?>[] parameterHandlers;

  //builder构建模式
  static final class Builder<T, R> {
    final Retrofit retrofit;
    final Method method;
    //方法的注解
    final Annotation[] methodAnnotations;
    //方法入参的注解,是个二维数组,因为一个入参可能有多个注解
    final Annotation[][] parameterAnnotationsArray;
    //参数类型数组
    final Type[] parameterTypes;
    //返回的类型
    Type responseType;
    //是否拿到了表单
    boolean gotField;
   //是否拿到了Part
    boolean gotPart;
  //是否拿到了Body
    boolean gotBody;
    boolean gotPath;
    boolean gotQuery;
    boolean gotUrl;
    String httpMethod;
    boolean hasBody;
    boolean isFormEncoded;
    boolean isMultipart;
    String relativeUrl;
    Headers headers;
    MediaType contentType;
    Set<String> relativeUrlParamNames;//相对路径里的参数,比如{}里的
    ParameterHandler<?>[] parameterHandlers;//参数处理器,封装了参数的解析结果
    Converter<ResponseBody, T> responseConverter;
    CallAdapter<T, R> callAdapter;
    //Builder的构造方法
    Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();
      this.parameterTypes = method.getGenericParameterTypes();
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }
    //build()方法
    public ServiceMethod build() {
      //创建一个callAdapter,adapter的作用是把一个类型的东西适配成另一个类型,这里的callAdapter
      //就是把okhttp的call转换成你需要的,比如跟rxjava配合使用就需要一个转换成observable的adapter
      callAdapter = createCallAdapter();
      //返回的response类型,便于解析
      responseType = callAdapter.responseType();
      //Response类型不被允许
      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?");
      }
      //创建response解析器,这里我们一般用gosn解析
      responseConverter = createResponseConverter();
      //逐个方法去解析其注解,parseMethodAnnotation字面意思就是解析方法注解
      for (Annotation annotation : methodAnnotations) {
        //这个方法是核心重点,后面会具体分析,建议先看完这个方法的解析再看后面的代码
        parseMethodAnnotation(annotation);
      }
      //一顿解析之后,开始判空,用多了retrofit应该对这些报错有点印象
      if (httpMethod == null) {
        //httpMethod 为空,说明你没有写@GET, @POST等网络请求方式注解
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }
      if (!hasBody) {  
        if (isMultipart) {
          throw methodError(
              //Multipart必须要附在有请求体上的请求
              "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).");
        }
      }
      //parameterCount 表示方法入参的数量,parameterAnnotationsArray是参数的注解
      //这是个二维数组,因为参数的注解可能有多个,外层数组是参数,第二层是参数的注解
      int parameterCount = parameterAnnotationsArray.length;
      //参数的处理,parameterHandlers 也是个数组
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        // 每个参数单独解析,parameterTypes是入参类型的数组,顺序存放
        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.");
      }
     //得到一个解析好的Method的封装
      return new ServiceMethod<>(this);
    }
   ...略
  }
...略
}

可以看到在他的Builder的build()方法里做了大量的解析工作,其实主要就是把方法里的那些注解和入参解析成okhttp到时候需要用到的元素。
来看看解析方法注解parseMethodAnnotation(Annotation annotation)方法:

//原来大佬的代码也会有很多if else if - -
// 这里拿到的annotation是网络请求方法上的注解,比如@POST,@GET这些,
//先判断他们是哪种请求,再拿到他们的value,传到
//parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody)
//做进一步解析
 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(String httpMethod, String value, boolean hasBody)方法,这里要明确一个事实,这些方法都是ServiceMethod.Builder类的内部方法,里面涉及到的成员变量都是ServiceMethod.Builder类的:

//解析http方法和路径
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
      //此时如果httpMethod 不为空了,报错,只允许注解一个http请求方式
      if (this.httpMethod != null) {
        throw methodError("Only one HTTP method is allowed. Found: %s and %s.",
            this.httpMethod, httpMethod);
      }
      //给这些成员变量赋值
      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()) {
          //不允许有替代字符创部分,如果要使用动态参数,就使用@Query
          //意思是不允许在url拼接动态请求参数{}
          throw methodError("URL query string \"%s\" must not have replace block. "
              + "For dynamic query parameters use @Query.", queryParams);
        }
      }
      //拿到相对url路径
      this.relativeUrl = value;
      //解析url里的参数名,提取{}里的参数
      this.relativeUrlParamNames = parsePathParameters(value);
    }

再来看看parseParameter(int p, Type parameterType, Annotation[] annotations)方法:

//解析参数,p代表第几个参数
 private ParameterHandler<?> parseParameter( int p, Type parameterType, Annotation[] annotations) {
      ParameterHandler<?> result = null;
      //遍历http相关的注解,有就返回
      for (Annotation annotation : annotations) {
        //解析参数注解,看看parseParameterAnnotation()方法
        ParameterHandler<?> annotationAction = parseParameterAnnotation(p, parameterType, annotations, annotation);
        if (annotationAction == null) {
          continue;
        }

        if (result != null) {
          throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
        }

        result = annotationAction;
      }

      if (result == null) {
        throw parameterError(p, "No Retrofit annotation found.");
      }

      return result;
    }

重点方法parseParameterAnnotation() ,有点长,但只是因为对各种类型的注解进行分别处理,其中的逻辑无非是拿到注解的值进行封装,这里只挑QUERY和BODY两个常见的注解来看,:

 private ParameterHandler<?> parseParameterAnnotation(
        int p, Type type, Annotation[] annotations, Annotation annotation) {
     if (annotation instanceof Query) {
        Query query = (Query) annotation;
        String name = query.value();
        boolean encoded = query.encoded();
       
        gotQuery = true;
        ...
        //这个converter 的作用在最终构建网络访问的时候会用到,因为是query注解,所以最终给出的肯定是string
        Converter<?, String> converter =
              retrofit.stringConverter(type, annotations);
        return new ParameterHandler.Query<>(name, converter, encoded);
      } 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.");
        }
        //因为是body注解,所以最终给出的是RequestBody
        Converter<?, RequestBody> 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封装了些什么,同样挑QUERY和BODY的看看:

//ParameterHandler是个接口类,里面有个apply抽象方法
abstract class ParameterHandler<T> {
  abstract void apply(RequestBuilder builder, @Nullable T value) throws IOException;

  
  //每一种参数注解都有一个对应的实现类,实现apply()方法,处理各自的独特流程
  static final class Query<T> extends ParameterHandler<T> {
    private final String name;
    private final Converter<T, String> valueConverter;
    private final boolean encoded;
    //构造方法
    Query(String name, Converter<T, String> valueConverter, boolean encoded) {
      this.name = checkNotNull(name, "name == null");
      this.valueConverter = valueConverter;
      this.encoded = encoded;
    }
    //这个apply方法最终是在构建请求的时候会用到,看他的入参有个RequestBuilder 
    @Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
      if (value == null) return; // Skip null values.
      //这个valueConverter是构造方法传进来的,需要把value转成string
      String queryValue = valueConverter.convert(value);
      if (queryValue == null) return; // Skip converted but null values
      //因为query的参数是string
      builder.addQueryParam(name, queryValue, encoded);
    }
  }

  static final class Body<T> extends ParameterHandler<T> {
    private final Converter<T, RequestBody> converter;

    Body(Converter<T, RequestBody> converter) {
      this.converter = converter;
    }

    @Override void apply(RequestBuilder builder, @Nullable T value) {
      if (value == null) {
        throw new IllegalArgumentException("Body parameter value must not be null.");
      }
      RequestBody body;
      try {
        //转成了requestBody
        body = converter.convert(value);
      } catch (IOException e) {
        throw new RuntimeException("Unable to convert " + value + " to RequestBody", e);
      }
    //requestBody才是okhttp里body里装的类型
      builder.setBody(body);
    }
  }
}
做下梳理,回到创建动态代理的那个方法:
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, @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);
            }
            //这里是解析method的重要方法,主要是各种注解的解析
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            //得到一个OkHttpCall,算是okhttp里的realCall
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //callAdapter如果添加了rxjava的会返回一个observable
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

通过loadServiceMethod()方法最终拿到了一个ServiceMethod,这个ServiceMethod里包含通过解析请求方法里拿到的各种封装体,来看看主要是哪些:

final class ServiceMethod<R, T> {
  // 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;
  final CallAdapter<R, T> callAdapter;

  private final HttpUrl baseUrl;
  private final Converter<ResponseBody, R> responseConverter;
  private final String httpMethod; //http访问方式 get还是post等
  private final String relativeUrl;//url的相对路径,就是host后面的那些
  private final Headers headers;//请求头,可以在方法上通过注解添加
  private final MediaType contentType;//传输类型
  private final boolean hasBody;//是否有请求体
  private final boolean isFormEncoded;//是否是表单提交
  private final boolean isMultipart;//是否是多部件提交
  private final ParameterHandler<?>[] parameterHandlers;//参数处理详情数组
  ...
}

至此一个网络请求的方法上的注解和入参都拿到了,再往下是如何访问网络:

//得到一个OkHttpCall,算是okhttp里的realCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//callAdapter如果添加了rxjava的会返回一个observable
 return serviceMethod.callAdapter.adapt(okHttpCall);

用ServiceMethod和方法参数值新建了一个OkHttpCall对象,熟悉okhttp的话应该知道这个call是能直接访问网络的,只不过在okhttp里是RealCall,实际上这个OkhttpCall可以说是RealCall的代理类,因为它里面就维护了一个成员变量call,最终可以发现那call是调用了OkhttpClient的newCall方法得到的。
再看serviceMethod.callAdapter.adapt(okHttpCall),serviceMethod的callAdapter是通过createCallAdapter()方法生成的:

  private CallAdapter<T, R> createCallAdapter() {
      Type returnType = method.getGenericReturnType();
      if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(
            "Method return type must not include a type variable or wildcard: %s", returnType);
      }
      if (returnType == void.class) {
        throw methodError("Service methods cannot return void.");
      }
      Annotation[] annotations = method.getAnnotations();
      try {
        //调用了retrofit的callAdapter
        return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }

retrofit.callAdapter():

  public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

  public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");
    //adapterFactories是Retrofit的变量,如果我们没有
    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;
      }
    }

    StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
        .append(returnType)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(adapterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(adapterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
  }

可以看到最终是在adapterFactories里取的,adapterFactories是adapter工厂集合,如果我们没有添加rxjava的adapter就会返回默认的一个工厂DefaultCallAdapterFactory:

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();

  @Override
  //通过它的get方法,拿到一个啥也没干的CallAdapter
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }

    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }
      //最终是调用这个方法,没有任何加工,直接返回入参call
      @Override public Call<Object> adapt(Call<Object> call) {
        return call;
      }
    };
  }
}

所以每个在serviceApi定义的方法,最终返回的就是一个OkHttpCall,看看OkHttpCall的主要代码:

final class OkHttpCall<T> implements Call<T> {
  //这个serviceMethod就是之前做了这么多注解解析得到的
  private final ServiceMethod<T, ?> serviceMethod;
  //这个方法的入参值
  private final @Nullable Object[] args;

  private volatile boolean canceled;

  @GuardedBy("this")
  //这个rawCall,顾名思义原始的call,其实他才是真正去做网络访问的
  private @Nullable okhttp3.Call rawCall;
  @GuardedBy("this")
  private @Nullable Throwable creationFailure; // Either a RuntimeException or IOException.
  @GuardedBy("this")
  private boolean executed;
  //构造方法
  OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }
  @Override 
  //enqueue方法,异步网络请求,okhttp走过一遍的话应该很熟悉
  public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "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 {
          //这个createRawCall()是关键
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }
    //最终还是调用的rawCall的enqueue()方法
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          //解析response
          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();
        }
      }
    });
  }

 private okhttp3.Call createRawCall() throws IOException {
    //这个toRequest()把那些解析出来的注解和参数类型转换成request
    Request request = serviceMethod.toRequest(args);
    //这个serviceMethod.callFactory就是OkHttpClient
    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 {
    //变形金刚大合体,这些入参都是之前通过解析注解拿到的
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart);

    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

    int argumentCount = args != null ? args.length : 0;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException("Argument count (" + argumentCount
          + ") doesn't match expected count (" + handlers.length + ")");
    }
    //ParameterHandler的apply()方法,之前我们分析过的,一个个转成okhttp需要的request参数
    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }
    //最终得到组装好的request
    return requestBuilder.build();
  }
retrofi的源码到此分析完毕,看完后觉得JakeWharton大神的代码实在是太。。。优雅了,里面涉及到很多设计模式,这些设计模式的运用,让这个看似复杂的okhttp封装变得层次分明,可读性和扩展性都很好,值得反复观摩学习。
最后做个retrofit的总结:

1,核心是运用了jdk动态代理技术,让网络访问中业务代码抽离开,实际的网络访问功能则封装得更容易使用。
2,网络访问的业务代码以接口和注解的形式编写,retrofit则是通过解析注解和参数来构造request。
3,最终每个接口方法返回了一个OkhttpCall,这是个okhttp里RealCall的代理类。

相关文章

网友评论

      本文标题:Retrofit源码解析

      本文链接:https://www.haomeiwen.com/subject/hordpltx.html