1. 程式人生 > >Retrofit原始碼解析---初始化

Retrofit原始碼解析---初始化

首先看下demo

1、首先定義請求模版介面

public interface IServiceDemo {
    @POST("login/nameAuth")
    Call<String> login(
            @Body User ueser);
}
2、定義Retrofit類
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://123.56.186.199:8080/map-mobile/")
                        //增加返回值為String的支援
                .addConverterFactory(ScalarsConverterFactory.create())
                        //增加返回值為Gson的支援(以實體類返回)
                .addConverterFactory(GsonConverterFactory.create())
                        //增加返回值為Oservable<T>的支援
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

3、使用介面獲取響應
IServiceDemo requestSerives = retrofit.create(IServiceDemo.class);//這裡採用的是Java的動態代理模式
        User user = new User();
        user.setMobile("18508480922");
        user.setPassword("111111");
        Call<String> call = requestSerives.login(user);//傳入我們請求的鍵值對的值
        call.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                System.out.println("return:" + response.body().toString());
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {
                System.out.println("失敗");
            }
        });

這一篇我們先看Retrofit的建立及介面的建立,下一篇看具體網路請求的執行,及先分析下面執行流程
       Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://123.56.186.199:8080/map-mobile/")
                        //增加返回值為String的支援
                .addConverterFactory(ScalarsConverterFactory.create())
                        //增加返回值為Gson的支援(以實體類返回)
                .addConverterFactory(GsonConverterFactory.create())
                        //增加返回值為Oservable<T>的支援
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

        IServiceDemo requestSerives = retrofit.create(IServiceDemo.class);//這裡採用的是Java的動態代理模式
        User user = new User();
        user.setMobile("18508480922");
        user.setPassword("111111");
        Call<String> call = requestSerives.login(user);//傳入我們請求的鍵值對的值
1、首先我們看下Retrofit的建立
    public Builder() {
      // 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是Retrofit的一個內部類,這裡會新增一個BuiltInConverters關於converterFactories後面會講
   public Builder baseUrl(String baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      HttpUrl httpUrl = HttpUrl.parse(baseUrl);
      if (httpUrl == null) {
        throw new IllegalArgumentException("Illegal URL: " + baseUrl);
      }
      return baseUrl(httpUrl);
    }
轉化為HttpUrl,然後呼叫baseUrl

   public Builder baseUrl(final HttpUrl baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      List<String> pathSegments = baseUrl.pathSegments();
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      return baseUrl(new BaseUrl() {
        @Override public HttpUrl url() {
          return baseUrl;
        }
      });
    }
   public Builder baseUrl(BaseUrl baseUrl) {
      this.baseUrl = checkNotNull(baseUrl, "baseUrl == null");
      return this;
    }
    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
新增converterFactories
    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

新增adapterFactories

最後呼叫build

 public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(Platform.get().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);
    }

這裡呼叫defaultCallAdapterFactory添加了一個預設的CallAdapter,最後使用前面的引數構造了一個Retrofit
  Retrofit(okhttp3.Call.Factory callFactory, BaseUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
      Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories;
    this.adapterFactories = adapterFactories;
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }

2、接下來我們看Service的建立
IServiceDemo requestSerives = retrofit.create(IServiceDemo.class);/
 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);
            }
            return loadMethodHandler(method).invoke(args);
          }
        });
  }
這裡使用了java的Proxy,最終方法的呼叫都會呼叫到這裡的invoke方法。

3、Service方法呼叫

Call<String> call = requestSerives.login(user);
呼叫到前面的invoke
    @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);
            }
            return loadMethodHandler(method).invoke(args);
          }
        });
前面兩個條件不滿足,最終呼叫loadMethodHandler(method).invoke(args);

先看loadMethodHandler(method)

  MethodHandler loadMethodHandler(Method method) {
    MethodHandler handler;
    synchronized (methodHandlerCache) {
      handler = methodHandlerCache.get(method);
      if (handler == null) {
        handler = MethodHandler.create(this, method);
        methodHandlerCache.put(method, handler);
      }
    }
    return handler;
  }

首先檢視該方法是否已經解析過,如果解析過直接返回,沒有的話重新建立一個,然後新增到快取,我們看下create方法
static MethodHandler create(Retrofit retrofit, Method method) {
    CallAdapter<?> callAdapter = createCallAdapter(method, retrofit);
    Type responseType = callAdapter.responseType();
    if (responseType == Response.class || responseType == okhttp3.Response.class) {
      throw Utils.methodError(method, "'"
          + Types.getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    Converter<ResponseBody, ?> responseConverter =
        createResponseConverter(method, retrofit, responseType);
    RequestFactory requestFactory = RequestFactoryParser.parse(method, responseType, retrofit);
    return new MethodHandler(retrofit.callFactory(), requestFactory, callAdapter,
        responseConverter);
  }
create方法做的事情比較多:

a)、解析Call介面卡,這個介面卡決定了整個呼叫的框架,如果是Call型別,則直接使用OkHttp的enque觸發請求,而如果是Observable型別,則通過Subscribe出發請求,包括把最後的返回值轉換為一個Observable

b)、建立返回值具體型別的Converter,如請求型別是自定義型別,則可能使用Gson轉為Gson格式

c)、建立請求引數的RequestFactory ,包括請求的具體地址,請求方法,請求引數如何解析,是否有body等。

d)、根據前面解析的值建立一個MethodHandler。

下面我們分別來看

a、解析Call介面卡

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

獲取返回值型別,判斷返回值是否可以解析以及是否為void型別,獲取方法上面的註解(請求路徑及方法),然後呼叫callAdapter
  public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }
 public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    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());
  }
nextCallAdapter從adapterFactories裡選擇一個合適的CallAdapter,對應Call是DefaultCallAdapterFactory,對應Observable是RxJavaCallAdapterFactory

這樣CallAdapter就建立完了

b)、建立返回值具體型別的Converter

  private static Converter<ResponseBody, ?> createResponseConverter(Method method,
      Retrofit retrofit, Type responseType) {
    Annotation[] annotations = method.getAnnotations();
    try {
      return retrofit.responseBodyConverter(responseType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw Utils.methodError(e, method, "Unable to create converter for %s", responseType);
    }
  }
獲取註解,接著呼叫responseBodyConverter
 public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
  }

public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
      Type type, Annotation[] annotations) {
    checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");

    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;
      }
    }

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

這裡我們的具體型別是String,這裡返回的Convert是ScalarsConverterFactory


c)、建立請求引數的RequestFactory

  static RequestFactory parse(Method method, Type responseType, Retrofit retrofit) {
    RequestFactoryParser parser = new RequestFactoryParser(method);

    Annotation[] methodAnnotations = method.getAnnotations();
    parser.parseMethodAnnotations(responseType, methodAnnotations);
    parser.parseParameters(retrofit, methodAnnotations);

    return parser.toRequestFactory(retrofit.baseUrl());
  }

獲取方法的註解,呼叫parseMethodAnnotations解析方法的註解,呼叫parseParameters解析引數,最後呼叫toRequestFactory返回一個RequestFactory結構

先看parseMethodAnnotations

private void parseMethodAnnotations(Type responseType, Annotation[] methodAnnotations) {
    for (Annotation annotation : methodAnnotations) {
      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(method, "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 Headers) {
        String[] headersToParse = ((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;
      }
    }

    if (httpMethod == null) {
      throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
    }
    if (!hasBody) {
      if (isMultipart) {
        throw methodError(method,
            "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
      }
      if (isFormEncoded) {
        throw methodError(method,
            "FormUrlEncoded can only be specified on HTTP methods with request body "
                + "(e.g., @POST).");
      }
    }
  }
這裡對各種Http方法進行解析,我們這裡是POST,最終呼叫
 parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);

private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
    if (this.httpMethod != null) {
      throw methodError(method, "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()) {
        throw methodError(method, "URL query string \"%s\" must not have replace block. "
            + "For dynamic query parameters use @Query.", queryParams);
      }
    }

    this.relativeUrl = value;
    this.relativeUrlParamNames = parsePathParameters(value);
  }
這裡還會呼叫parsePathParameters對路徑上的引數進行解析
  static Set<String> parsePathParameters(String path) {
    Matcher m = PARAM_URL_REGEX.matcher(path);
    Set<String> patterns = new LinkedHashSet<>();
    while (m.find()) {
      patterns.add(m.group(1));
    }
    return patterns;
  }


接下來看parseParameters解析方法中的請求引數及註解

這個函式比較長,我們只看我們涉及到的一部分

Type[] parameterTypes = method.getGenericParameterTypes();
    Annotation[][] parameterAnnotationsArray = method.getParameterAnnotations();
獲取引數型別和註解
 for (int i = 0; i < count; i++) {
      Type parameterType = parameterTypes[i];
      if (Utils.hasUnresolvableType(parameterType)) {
        throw parameterError(i, "Parameter type must not include a type variable or wildcard: %s",
            parameterType);
      }

      Annotation[] parameterAnnotations = parameterAnnotationsArray[i];

for迴圈對請求引數和註解進行解析,我們這裡註解的型別是Body
} else if (parameterAnnotation instanceof Body) {
            if (isFormEncoded || isMultipart) {
              throw parameterError(i,
                  "@Body parameters cannot be used with form or multi-part encoding.");
            }
            if (gotBody) {
              throw parameterError(i, "Multiple @Body method annotations found.");
            }

            Converter<?, RequestBody> converter;
            try {
              converter = retrofit.requestBodyConverter(parameterType, parameterAnnotations,
                  methodAnnotations);
            } catch (RuntimeException e) { // Wide exception range because factories are user code.
              throw parameterError(e, i, "Unable to create @Body converter for %s", parameterType);
            }
            action = new RequestAction.Body<>(converter);
            gotBody = true;
          }

          if (action != null) {
            if (requestActions[i] != null) {
              throw parameterError(i, "Multiple Retrofit annotations found, only one allowed.");
            }
            requestActions[i] = action;
          }
這裡可以看到body不能和form or multi-part encoding一起使用,且Body註解只能有一個
   converter = retrofit.requestBodyConverter(parameterType, parameterAnnotations,
                  methodAnnotations);
這裡獲取引數的convert解析器,和前面解析返回值具體型別的方式是一樣的,不過這裡我們是自定義類,返回的convert是GsonConverterFactory,把convert儲存到requestActions[i]

最後是toRequestFactory方法

  private RequestFactory toRequestFactory(BaseUrl baseUrl) {
    return new RequestFactory(httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody,
        isFormEncoded, isMultipart, requestActions);
  }
這裡根據前面的值建立一個RequestFactory
  RequestFactory(String method, BaseUrl baseUrl, String relativeUrl, Headers headers,
      MediaType contentType, boolean hasBody, boolean isFormEncoded, boolean isMultipart,
      RequestAction[] requestActions) {
    this.method = method;
    this.baseUrl = baseUrl;
    this.relativeUrl = relativeUrl;
    this.headers = headers;
    this.contentType = contentType;
    this.hasBody = hasBody;
    this.isFormEncoded = isFormEncoded;
    this.isMultipart = isMultipart;
    this.requestActions = requestActions;
  }

這樣的話RequestFactory就建立好了,

d)、根據前面解析的值建立一個MethodHandler

  private MethodHandler(okhttp3.Call.Factory callFactory, RequestFactory requestFactory,
      CallAdapter<?> callAdapter, Converter<ResponseBody, ?> responseConverter) {
    this.callFactory = callFactory;
    this.requestFactory = requestFactory;
    this.callAdapter = callAdapter;
    this.responseConverter = responseConverter;
  }




回到前面的invoke方法,接著呼叫前面返回值(MethodHandler)的invoke方法

 Object invoke(Object... args) {
    return callAdapter.adapt(
        new OkHttpCall<>(callFactory, requestFactory, args, responseConverter));
  }

這裡使用前面的引數構造了一個OkHttpCall然後這裡的callAdapter是DefaultCallAdapterFactory
@Override public <R> Call<R> adapt(Call<R> call) {
        return call;
      }
直接返回了call,也即我們剛建立的OkHttpCall

這樣通過呼叫Service的方法,我們就獲取到了一個OkHttpCall,OkHttpCall通過enqueue來啟動一個請求。下一篇我們分析請求的執行過程。