Retrofit解析8之核心解析——ServiceMethod及注解2

整體Retrofit內(nèi)容如下:

由于簡(jiǎn)述篇幅的限制贮懈,接上一篇文章繼續(xù)

3.2.8压恒、 Builder的方法parseParameter解析

看名字這個(gè)方法我們理解為解析參數(shù)的方法

    private ParameterHandler<?> parseParameter(
        int p, Type parameterType, Annotation[] annotations) {
      // 定義一個(gè)ParameterHandler 變量
      ParameterHandler<?> result = null;
      //parseParameterAnnotation方法來獲取對(duì)應(yīng)的ParameterHandler對(duì)象
      for (Annotation annotation : annotations) {
        ParameterHandler<?> annotationAction = parseParameterAnnotation(
            p, parameterType, annotations, annotation);
        if (annotationAction == null) {
          continue;
        }
        if (result != null) {
          throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
        }
       //對(duì)之前定義的變量賦值
        result = annotationAction;
      }
      //非空檢查
      if (result == null) {
        throw parameterError(p, "No Retrofit annotation found.");
      }
      return result;
    }

這個(gè)方法內(nèi)部很簡(jiǎn)單,主要就是通過遍歷annotations错邦,內(nèi)部調(diào)用parseParameterAnnotation來獲取ParameterHandler對(duì)象并返回探赫。
那讓我們來看看parseParameterAnnotation()方法里面是怎么調(diào)用的

3.2.9、 Builder的方法parseParameterAnnotation解析
private ParameterHandler<?> parseParameterAnnotation(
        int p, Type type, Annotation[] annotations, Annotation annotation) {
        //如果注解是 @Url
      if (annotation instanceof Url) {
         //默認(rèn)是在這里給gotUrl賦值的撬呢,且只能賦值一次伦吠,如果gotUrl==true,則說明之前賦值過魂拦,拋異常
        if (gotUrl) {
          throw parameterError(p, "Multiple @Url method annotations found.");
        }
        //@Url 注解和@Path 是互斥的毛仪,所以不能并存,發(fā)現(xiàn)并存則拋異常
        if (gotPath) {
          throw parameterError(p, "@Path parameters may not be used with @Url.");
        }
        //如果已經(jīng)使用了@Query芯勘、@QueryMap或者@QueryName箱靴,會(huì)出問題,因?yàn)閼?yīng)該先使用@Url 后才能配置Query等的注解
        if (gotQuery) {
          throw parameterError(p, "A @Url parameter must not come after a @Query");
        }
         //如果設(shè)置了relativeUrl荷愕,說明已經(jīng)動(dòng)態(tài)配置過url衡怀,所以這時(shí)候不能再使用@Url 注解
        if (relativeUrl != null) {
          throw parameterError(p, "@Url cannot be used with @%s URL", httpMethod);
        }
        //給gotUrl賦值為true
        gotUrl = true;
        //類型判斷
        if (type == HttpUrl.class
            || type == String.class
            || type == URI.class
            || (type instanceof Class && "android.net.Uri".equals(((Class<?>) type).getName()))) {
          //返回ParameterHandler的靜態(tài)內(nèi)部類RelativeUrl
          return new ParameterHandler.RelativeUrl();
           //至此解析@Url 完畢
        } else {
          throw parameterError(p,
              "@Url must be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri type.");
        }
        //如果是@ Path 注解
      } else if (annotation instanceof Path) {
         //如果已經(jīng)設(shè)置了gotQuery,說明之前解析過@Query、@QueryMap或者@QueryName安疗,這會(huì)導(dǎo)致動(dòng)態(tài)配置的異常抛杨,所以拋異常
        if (gotQuery) {
          throw parameterError(p, "A @Path parameter must not come after a @Query.");
        }
        //上面解釋過,@Path和@Url是互斥的
        if (gotUrl) {
          throw parameterError(p, "@Path parameters may not be used with @Url.");
        }
        //如果設(shè)置了relativeUrl為null荐类,無法進(jìn)行動(dòng)態(tài)配置怖现,所以會(huì)拋異常
        if (relativeUrl == null) {
          throw parameterError(p, "@Path can only be used with relative url on @%s", httpMethod);
        }
         //給gotPath賦值
        gotPath = true;
        //獲取Path對(duì)象
        Path path = (Path) annotation;
        String name = path.value();
         //通過正則表達(dá)式檢查是否符合要求
        validatePathName(p, name);
        //調(diào)用retrofit的stringConverter來獲取一個(gè)轉(zhuǎn)換器,通過泛型我們知道這個(gè)轉(zhuǎn)化器的輸出是String
        Converter<?, String> converter = retrofit.stringConverter(type, annotations);
        //返回ParameterHandler的靜態(tài)內(nèi)部類Path對(duì)象
        return new ParameterHandler.Path<>(name, converter, path.encoded());
        //至此解析@Path結(jié)束
        //如果是@Query   注解
      } else if (annotation instanceof Query) {
         //類型轉(zhuǎn)化玉罐,獲取對(duì)應(yīng)的值
        Query query = (Query) annotation;
        String name = query.value();
        boolean encoded = query.encoded();
        //獲取真實(shí)的類型
        Class<?> rawParameterType = Utils.getRawType(type);
        //給gotQuery賦值屈嗤,說明已經(jīng)使用了 注解
        gotQuery = true;
         //如果rawParameterType是Iterable接口的子類
        if (Iterable.class.isAssignableFrom(rawParameterType)) {
           //如果不是參數(shù)化的類型,則拋出異常
          if (!(type instanceof ParameterizedType)) {
            throw parameterError(p, rawParameterType.getSimpleName()
                + " must include generic type (e.g., "
                + rawParameterType.getSimpleName()
                + "<String>)");
          }
          //如果是參數(shù)化的類型吊输,則進(jìn)行強(qiáng)制類型轉(zhuǎn)化
          ParameterizedType parameterizedType = (ParameterizedType) type;
          //獲取第一個(gè)入?yún)⒌膮?shù)類型
          Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
         //獲取輸出類型是String的轉(zhuǎn)化器
          Converter<?, String> converter =
              retrofit.stringConverter(iterableType, annotations);
          //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Query饶号,然后調(diào)用iterable()方法 獲取一個(gè)新的ParameterHandler對(duì)象
          return new ParameterHandler.Query<>(name, converter, encoded).iterable();
            //如果類型是數(shù)組類型的
        } else if (rawParameterType.isArray()) {
          //如果是基本基本類型則需要裝箱操作
          Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
          //獲取輸出類型是String的轉(zhuǎn)化器
          Converter<?, String> converter =
              retrofit.stringConverter(arrayComponentType, annotations);
           //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Query,然后調(diào)用array()方法 獲取一個(gè)新的ParameterHandler對(duì)象璧亚。
          return new ParameterHandler.Query<>(name, converter, encoded).array();
        } else {
          //如果既不是集合也不是數(shù)組類型讨韭,則是普通類型
          //獲取輸出類型的是String的類型轉(zhuǎn)化器
          Converter<?, String> converter =
              retrofit.stringConverter(type, annotations);
          //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Query
          return new ParameterHandler.Query<>(name, converter, encoded);
        }
        //自此 解析@Query 完畢
        //如果是 @QueryName 注解
      } else if (annotation instanceof QueryName) {
        //獲取QueryName 注解的值
        QueryName query = (QueryName) annotation;
        boolean encoded = query.encoded();
        //獲取原始類型
        Class<?> rawParameterType = Utils.getRawType(type);
        gotQuery = true;
         //如果rawParameterType是Iterable接口的子類
        if (Iterable.class.isAssignableFrom(rawParameterType)) {
          if (!(type instanceof ParameterizedType)) {
            throw parameterError(p, rawParameterType.getSimpleName()
                + " must include generic type (e.g., "
                + rawParameterType.getSimpleName()
                + "<String>)");
          }
          //如果是參數(shù)化的類型,則進(jìn)行強(qiáng)制類型轉(zhuǎn)化
          ParameterizedType parameterizedType = (ParameterizedType) type;
            //獲取第一個(gè)入?yún)⒌膮?shù)類型
          Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
          //獲取輸出類型是String的轉(zhuǎn)化器
          Converter<?, String> converter =
              retrofit.stringConverter(iterableType, annotations);
           //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類QueryName癣蟋,然后調(diào)用iterable()方法 獲取一個(gè)新的ParameterHandler對(duì)象透硝。
          return new ParameterHandler.QueryName<>(converter, encoded).iterable();
             //如果類型是數(shù)組類型的
        } else if (rawParameterType.isArray()) {
            //如果是基本基本類型則需要裝箱操作
          Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
          //獲取輸出類型是String的轉(zhuǎn)化器
          Converter<?, String> converter =
              retrofit.stringConverter(arrayComponentType, annotations);
            //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類QueryName,然后調(diào)用array()方法 獲取一個(gè)新的ParameterHandler對(duì)象疯搅。
          return new ParameterHandler.QueryName<>(converter, encoded).array();
        } else {
          //如果既不是集合也不是數(shù)組類型濒生,則是普通類型
          //獲取輸出類型的是String的類型轉(zhuǎn)化器
          Converter<?, String> converter =
              retrofit.stringConverter(type, annotations);
             //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類QueryName
          return new ParameterHandler.QueryName<>(converter, encoded);
        }
       //如果是 @QueryMap 注解,
      } else if (annotation instanceof QueryMap) {
          //獲取原始的類型 
        Class<?> rawParameterType = Utils.getRawType(type);
         //如果不是Map的接口的子類幔欧,拋異常
        if (!Map.class.isAssignableFrom(rawParameterType)) {
          throw parameterError(p, "@QueryMap parameter type must be Map.");
        }
         //獲取類型的超類
        Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
        //如果不是參數(shù)類型罪治,則拋異常
        if (!(mapType instanceof ParameterizedType)) {
          throw parameterError(p, "Map must include generic types (e.g., Map<String, String>)");
        }
        //強(qiáng)制類型轉(zhuǎn)化
        ParameterizedType parameterizedType = (ParameterizedType) mapType;
        //獲取第一個(gè)入?yún)⒌膮?shù)類型丽声,其實(shí)就是map中key的類型,一般是String
        Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
         //如果不是String 類型觉义,則拋異常
        if (String.class != keyType) {
          throw parameterError(p, "@QueryMap keys must be of type String: " + keyType);
        }
         //獲取第二個(gè)參數(shù)的類型,也就是value的值
        Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
        //獲取輸出是String的轉(zhuǎn)化器
        Converter<?, String> valueConverter =
            retrofit.stringConverter(valueType, annotations);
         //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類QueryMap雁社,并返回
        return new ParameterHandler.QueryMap<>(valueConverter, ((QueryMap) annotation).encoded());
        //如果是@Header 注解
      } else if (annotation instanceof Header) {
        //獲取header的值
        Header header = (Header) annotation;
        String name = header.value();
         //獲取原始類型
        Class<?> rawParameterType = Utils.getRawType(type);
          //如果是Iterable的子類
        if (Iterable.class.isAssignableFrom(rawParameterType)) {
           //參數(shù)類型判斷
          if (!(type instanceof ParameterizedType)) {
            throw parameterError(p, rawParameterType.getSimpleName()
                + " must include generic type (e.g., "
                + rawParameterType.getSimpleName()
                + "<String>)");
          }
          ParameterizedType parameterizedType = (ParameterizedType) type;
          //獲取第一個(gè)參數(shù)的類型
          Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
          //獲取輸出是String 類型的轉(zhuǎn)化器
          Converter<?, String> converter =
              retrofit.stringConverter(iterableType, annotations);
             //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Header,然后調(diào)用iterable()方法 獲取一個(gè)新的ParameterHandler對(duì)象
          return new ParameterHandler.Header<>(name, converter).iterable();
           //如果是數(shù)組類型
        } else if (rawParameterType.isArray()) {
           //裝箱操作
          Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
          //獲取輸出為String 類型的 轉(zhuǎn)換器
          Converter<?, String> converter =
              retrofit.stringConverter(arrayComponentType, annotations);
                 //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Header晒骇,然后調(diào)用array()方法 獲取一個(gè)新的ParameterHandler對(duì)象霉撵。
          return new ParameterHandler.Header<>(name, converter).array();
        } else {
           //如果既不是迭代器也不是數(shù)組,則是普通類型
          //獲取輸出為String 類型的 轉(zhuǎn)換器
          Converter<?, String> converter =
              retrofit.stringConverter(type, annotations);
           //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Header
          return new ParameterHandler.Header<>(name, converter);
        }
        //如果是@HeaderMap 注解
      } else if (annotation instanceof HeaderMap) {
         //獲取參數(shù)的原始類型
        Class<?> rawParameterType = Utils.getRawType(type);
        //如果不是Map接口類型的子類洪囤,則拋異常
        if (!Map.class.isAssignableFrom(rawParameterType)) {
          throw parameterError(p, "@HeaderMap parameter type must be Map.");
        }
         //獲取類型的超類
        Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
          //參數(shù)類型判斷
        if (!(mapType instanceof ParameterizedType)) {
          throw parameterError(p, "Map must include generic types (e.g., Map<String, String>)");
        }
        ParameterizedType parameterizedType = (ParameterizedType) mapType;
         //獲取第一個(gè)參數(shù)的類型徒坡,是key的類型
        Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
        //key值 一定是String的,不是String 則拋異常
        if (String.class != keyType) {
          throw parameterError(p, "@HeaderMap keys must be of type String: " + keyType);
        }
         //獲取value的類型
        Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
        //獲取輸出是 String的轉(zhuǎn)化器
        Converter<?, String> valueConverter =
            retrofit.stringConverter(valueType, annotations);
        //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類HeaderMap
        return new ParameterHandler.HeaderMap<>(valueConverter);
         // 如果是 @Field 
      } else if (annotation instanceof Field) {
         // 如果沒有使用方法注解 @isFormEncoded瘤缩,卻使用參數(shù)注解@Field喇完,則拋出異常
        if (!isFormEncoded) {
          throw parameterError(p, "@Field parameters can only be used with form encoding.");
        }  
        // 獲取 注解的內(nèi)容
        Field field = (Field) annotation;
        String name = field.value();
        boolean encoded = field.encoded();
        // 給gotField賦值
        gotField = true;
         //獲取原始類型
        Class<?> rawParameterType = Utils.getRawType(type);
         // 如果是Iterable類的子類
        if (Iterable.class.isAssignableFrom(rawParameterType)) {
          // 參數(shù)類型判斷
          if (!(type instanceof ParameterizedType)) {
            throw parameterError(p, rawParameterType.getSimpleName()
                + " must include generic type (e.g., "
                + rawParameterType.getSimpleName()
                + "<String>)");
          }
          ParameterizedType parameterizedType = (ParameterizedType) type;
           // 獲取第一個(gè)參數(shù)的類型
          Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
           //獲取 輸出是String類型的 轉(zhuǎn)化器
          Converter<?, String> converter =
              retrofit.stringConverter(iterableType, annotations);
             //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Field,然后調(diào)用iterable()方法 獲取一個(gè)新的ParameterHandler對(duì)象
          return new ParameterHandler.Field<>(name, converter, encoded).iterable();
          //如果是 數(shù)組類型
        } else if (rawParameterType.isArray()) {
           //裝箱操作
          Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
          //獲取輸出是String的 轉(zhuǎn)化器
          Converter<?, String> converter =
              retrofit.stringConverter(arrayComponentType, annotations);
               //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Field剥啤,然后調(diào)用array()方法 獲取一個(gè)新的ParameterHandler對(duì)象锦溪。
          return new ParameterHandler.Field<>(name, converter, encoded).array();
        } else {
          // 如果既不是集合也不是數(shù)組類型,則是普通類型
          //獲取 輸出是String類型轉(zhuǎn)化器
          Converter<?, String> converter =
              retrofit.stringConverter(type, annotations);
           //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Field
          return new ParameterHandler.Field<>(name, converter, encoded);
        }
         //如果@注解 是FieldMap
      } else if (annotation instanceof FieldMap) {
          //如果不是表單提交則拋異常
        if (!isFormEncoded) {
          throw parameterError(p, "@FieldMap parameters can only be used with form encoding.");
        }
         //獲取原始類型
        Class<?> rawParameterType = Utils.getRawType(type);
         // 如果不是Map接口 铐殃,拋 異常
        if (!Map.class.isAssignableFrom(rawParameterType)) {
          throw parameterError(p, "@FieldMap parameter type must be Map.");
        }
         // 獲取 類型的 超類
        Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
         // 參數(shù)類型判斷
        if (!(mapType instanceof ParameterizedType)) {
          throw parameterError(p,
              "Map must include generic types (e.g., Map<String, String>)");
        }
        ParameterizedType parameterizedType = (ParameterizedType) mapType;
         // 獲取key的 類型
        Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
         // key值一定是String
        if (String.class != keyType) {
          throw parameterError(p, "@FieldMap keys must be of type String: " + keyType);
        }
         // 獲取value的 類型
        Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
        // 獲取 輸出類型是String的轉(zhuǎn)化器
        Converter<?, String> valueConverter =
            retrofit.stringConverter(valueType, annotations);
         //給 gotField 賦值
        gotField = true;
        //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類FieldMap海洼。
        return new ParameterHandler.FieldMap<>(valueConverter, ((FieldMap) annotation).encoded());
       // 如果 是@ Part 注解
      } else if (annotation instanceof Part) {
        //如果沒有使用@isMultipart 注解則拋異常
        if (!isMultipart) {
          throw parameterError(p, "@Part parameters can only be used with multipart encoding.");
        }
        //獲取 @Part 注解的值
        Part part = (Part) annotation;
        gotPart = true;
        String partName = part.value();
         //獲取原始類型
        Class<?> rawParameterType = Utils.getRawType(type);
         //如果 partName 是空的
        if (partName.isEmpty()) {
           // 類型是Iterable接口的子類
          if (Iterable.class.isAssignableFrom(rawParameterType)) {
             // 如果不是參數(shù)類型,則拋異常
            if (!(type instanceof ParameterizedType)) {
              throw parameterError(p, rawParameterType.getSimpleName()
                  + " must include generic type (e.g., "
                  + rawParameterType.getSimpleName()
                  + "<String>)");
            }
            ParameterizedType parameterizedType = (ParameterizedType) type;
            // 獲取第一個(gè)參數(shù)的類型
            Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
            //如果原始類型不是MultipartBody.Part的子類富腊,則拋異常
            if (!MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(iterableType))) {
              throw parameterError(p,
                  "@Part annotation must supply a name or use MultipartBody.Part parameter type.");
            }
            // 返回ParameterHandler內(nèi)部類RawPart.INSTANCE的iterable()方法
            return ParameterHandler.RawPart.INSTANCE.iterable();
            //如果是數(shù)組類型
          } else if (rawParameterType.isArray()) {
             // 獲取類的組件類型的數(shù)組
            Class<?> arrayComponentType = rawParameterType.getComponentType();
            //如果不是Part類子類,則拋異常
            if (!MultipartBody.Part.class.isAssignableFrom(arrayComponentType)) {
              throw parameterError(p,
                  "@Part annotation must supply a name or use MultipartBody.Part parameter type.");
            }
           // 返回ParameterHandler內(nèi)部類RawPart.INSTANCE的array()方法
            return ParameterHandler.RawPart.INSTANCE.array();
            //如果是MultipartBody.Part的子類
          } 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.");
          }
          //partName不為空
        } else {
          //定義Header
          Headers headers =
              Headers.of("Content-Disposition", "form-data; name=\"" + partName + "\"",
                  "Content-Transfer-Encoding", part.encoding());
           //如果類型是Iterable的子類
          if (Iterable.class.isAssignableFrom(rawParameterType)) {
            //參數(shù)類型判斷
            if (!(type instanceof ParameterizedType)) {
              throw parameterError(p, rawParameterType.getSimpleName()
                  + " must include generic type (e.g., "
                  + rawParameterType.getSimpleName()
                  + "<String>)");
            }
            ParameterizedType parameterizedType = (ParameterizedType) type;
            //獲取 第一個(gè)參數(shù)的類型
            Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
              //使用@Part 注解且注解內(nèi)部有值域帐,則不能和MultipartBody.Part一起使用赘被,例如:@Part("description") RequestBody description是可以的,@Part MultipartBody.Part file也是可以的肖揣,但是@Partt("file")  MultipartBody.Part file 是不可以的民假。
            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.");
            }
            //獲取輸出是RequestBody的轉(zhuǎn)化器
            Converter<?, RequestBody> converter =
                retrofit.requestBodyConverter(iterableType, annotations, methodAnnotations);
             // 返回ParameterHandler內(nèi)部類Part的實(shí)例,然后調(diào)用的iterable()方法返回一個(gè)ParameterHandler對(duì)象
            return new ParameterHandler.Part<>(headers, converter).iterable();
             //如果類型是數(shù)組類型
          } else if (rawParameterType.isArray()) {
            //獲取數(shù)組類型的類型
            Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
           //同理不能使用MultipartBody.Part.和有值的@Part 注解
            if (MultipartBody.Part.class.isAssignableFrom(arrayComponentType)) {
              throw parameterError(p, "@Part parameters using the MultipartBody.Part must not "
                  + "include a part name in the annotation.");
            }
            //獲取輸出是RequestBody的轉(zhuǎn)化器
            Converter<?, RequestBody> converter =
                retrofit.requestBodyConverter(arrayComponentType, annotations, methodAnnotations);
             // 返回ParameterHandler內(nèi)部類Part的實(shí)例龙优,然后調(diào)用的array()方法返回一個(gè)ParameterHandler對(duì)象
            return new ParameterHandler.Part<>(headers, converter).array();
            //如果既不是數(shù)組也是Iterable,但是普通類型也不能讓@Part的值有值且同時(shí)使用MultipartBody.Part
          } 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 {
            //不是MultipartBody.Par類型羊异,則獲取輸出是RequestBody的轉(zhuǎn)化器
            Converter<?, RequestBody> converter =
                retrofit.requestBodyConverter(type, annotations, methodAnnotations);
            //構(gòu)建ParameterHandler的靜態(tài)內(nèi)部類Part
            return new ParameterHandler.Part<>(headers, converter);
          }
        }
      //如果是@PartMap 注解
      } else if (annotation instanceof PartMap) {
        //沒有使用@isMultipart 拋異常。
        if (!isMultipart) {
          throw parameterError(p, "@PartMap parameters can only be used with multipart encoding.");
        }
        //給gotPart賦值
        gotPart = true;
         //獲取原始類型
        Class<?> rawParameterType = Utils.getRawType(type);
         //如果不是Map的類型彤断,則拋異常
        if (!Map.class.isAssignableFrom(rawParameterType)) {
          throw parameterError(p, "@PartMap parameter type must be Map.");
        }
        //獲取類型的超類
        Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
         //參數(shù)類型判斷
        if (!(mapType instanceof ParameterizedType)) {
          throw parameterError(p, "Map must include generic types (e.g., Map<String, String>)");
        }
        ParameterizedType parameterizedType = (ParameterizedType) mapType;
         //獲取key的類型
        Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
         //排除key不是String的類型
        if (String.class != keyType) {
          throw parameterError(p, "@PartMap keys must be of type String: " + keyType);
        }
        //獲取value的類型
        Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
        //@PartMap 不能和 @MultipartBody.Part 一起使用
        if (MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(valueType))) {
          throw parameterError(p, "@PartMap values cannot be MultipartBody.Part. "
              + "Use @Part List<Part> or a different value type instead.");
        }
         //獲取輸出是RequestBody的 轉(zhuǎn)換器
        Converter<?, RequestBody> valueConverter =
            retrofit.requestBodyConverter(valueType, annotations, methodAnnotations);
        PartMap partMap = (PartMap) annotation;
         //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類PartMap野舶。
        return new ParameterHandler.PartMap<>(valueConverter, partMap.encoding());
        // 如果注解是 @Body
      } else if (annotation instanceof Body) {
         //@Body 注解是不能和 @FormEncoded @Multipart 注解一起使用,如果一起使用拋異常
        if (isFormEncoded || isMultipart) {
          throw parameterError(p,
              "@Body parameters cannot be used with form or multi-part encoding.");
        }
         //@Body 只能使用一次
        if (gotBody) {
          throw parameterError(p, "Multiple @Body method annotations found.");
        }
        // 輸出是RequestBody的 轉(zhuǎn)化器
        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
        gotBody = true;
         //構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Body宰衙。
        return new ParameterHandler.Body<>(converter);
      }
      //如果上面都處理平道,則說明使用了一個(gè)非Retrofit的的注解,返回null
      return null; // Not a Retrofit annotation.
    }

內(nèi)容如下:

主要是根據(jù)具體的參數(shù)注解類型供炼,然后具體處理一屋。
補(bǔ)充一個(gè)問題:
Path注解與Url注解不能同時(shí)使用窘疮,否則會(huì)拋出paramterError錯(cuò)誤,其實(shí)原因有很好理解冀墨,Path注解用于替換url路徑中參數(shù)闸衫,這就要求在使用path注解時(shí),必須贏存在請(qǐng)求路徑诽嘉,不然沒法替換路徑中指定的參數(shù)楚堤,而Url注解是在參數(shù)中指定的請(qǐng)求路徑的,這個(gè)時(shí)候指定請(qǐng)求路徑已經(jīng)晚了含懊,path注解找不到請(qǐng)求路徑身冬,更別提更換請(qǐng)求路徑中的參數(shù)了。

3.2.10岔乔、 Builder的方法validatePathName解析

看方法名字 是檢驗(yàn)路徑名字

    private void validatePathName(int p, String name) {
      if (!PARAM_NAME_REGEX.matcher(name).matches()) {
        throw parameterError(p, "@Path parameter name must match %s. Found: %s",
            PARAM_URL_REGEX.pattern(), name);
      }
      // Verify URL replacement name is actually present in the URL path.
      if (!relativeUrlParamNames.contains(name)) {
        throw parameterError(p, "URL \"%s\" does not contain \"{%s}\".", relativeUrl, name);
      }
    }

根據(jù)正則表達(dá)式酥筝,來判斷url是否正確

3.2.11、 Builder的方法createResponseConverter解析

通過方法名雏门,我們猜是創(chuàng)建響應(yīng)轉(zhuǎn)化器

    private Converter<ResponseBody, T> createResponseConverter() {
       //獲取方法的注解
      Annotation[] annotations = method.getAnnotations();
      try {
        //調(diào)用retrofit的responseBodyConverter()方法來獲取一個(gè)輸入是ResponseBody的轉(zhuǎn)化器
        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);
      }
    }

主要是調(diào)用Retrofit的responseBodyConverter()來獲取輸入是ResponseBody的轉(zhuǎn)化器嘿歌,關(guān)于Retrofit我下面再介紹

3.2.12、 Builder的方法methodError解析

主要就是輸出錯(cuò)誤信息

    private RuntimeException methodError(String message, Object... args) {
      return methodError(null, message, args);
    }

    private RuntimeException methodError(Throwable cause, String message, Object... args) {
      message = String.format(message, args);
      return new IllegalArgumentException(message
          + "\n    for method "
          + method.getDeclaringClass().getSimpleName()
          + "."
          + method.getName(), cause);
    }
3.2.13茁影、 Builder的方法parameterError解析

輸出參數(shù)錯(cuò)誤

    private RuntimeException parameterError(
        Throwable cause, int p, String message, Object... args) {
      return methodError(cause, message + " (parameter #" + (p + 1) + ")", args);
    }

    private RuntimeException parameterError(int p, String message, Object... args) {
      return methodError(message + " (parameter #" + (p + 1) + ")", args);
    }

至此宙帝,ServiceMethod類已經(jīng)講解完畢了,大家對(duì)這個(gè)類熟悉了嗎募闲?
ok步脓,我們來看最后一個(gè)類Retrofit類

三、Retrofit

(一) 類注釋

老規(guī)矩先來認(rèn)識(shí)下這個(gè)類浩螺,首先看這個(gè)類的注釋

Retrofit adapts a Java interface to HTTP calls by using annotations on the declared methods to define how requests are made. Create instances using {@linkplain Builder the builder} and pass your interface to {@link #create} to generate an implementation.

翻譯一下:
Retroft把一個(gè)java接口的抽象方法 適配/轉(zhuǎn)化 成一個(gè)HTTP的請(qǐng)求靴患,它內(nèi)部是使用解析接口內(nèi)部的抽象方法上的注解來定義如何去發(fā)起請(qǐng)求。通過Builder可以創(chuàng)建Retroft的實(shí)例要出,通過調(diào)用create()方法來創(chuàng)建一個(gè)接口的具體實(shí)現(xiàn)類鸳君。

(二) 類代碼解析

由于這個(gè)類的代碼比價(jià)長(zhǎng),我就不全部粘貼患蹂,等用到時(shí)候再一一粘貼

1或颊、變量解析

那我們來看下他對(duì)應(yīng)的變量,內(nèi)容不多也比較簡(jiǎn)單,比較復(fù)雜的传于,我直接在上注釋了囱挑。

  //serviceMethod對(duì)象集合的緩存,用于重用格了,由于里面用到了反射看铆,大家知道反射比較消耗性能,所以為了避免重復(fù)反射盛末,節(jié)約性能弹惦,使用緩存否淤,保證只反射一次。
  private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
  final okhttp3.Call.Factory callFactory;
  final HttpUrl baseUrl;
  //轉(zhuǎn)化工廠  集合
  final List<Converter.Factory> converterFactories;
  // 請(qǐng)求適配工廠  集合
  final List<CallAdapter.Factory> adapterFactories;
  // 回調(diào)的線程池
  final Executor callbackExecutor;
  //如果為true棠隐,程序是在做一個(gè)預(yù)處理的操作石抡,只是提前創(chuàng)建了一些MethodHandler對(duì)象在緩存中。
  final boolean validateEagerly;
  • 以上所有變量都是final的助泽,所以構(gòu)造的時(shí)候賦值了啰扛,不會(huì)二次賦值
  • 這里提一下validateEagerly變量,他是和eagerlyValidateMethods對(duì)應(yīng)的嗡贺,后面再詳細(xì)講解隐解。
2、構(gòu)造函數(shù)解析
  Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
      Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
    this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }
  • 構(gòu)造函數(shù)很簡(jiǎn)單诫睬,就是賦值
  • 里面調(diào)用了Collections.unmodifiableList的方法檢查是否是List煞茫,注意他的導(dǎo)包"import static java.util.Collections.unmodifiableList",值得我們學(xué)習(xí)。
  • 構(gòu)造既不是public也不是private摄凡,所以不能在包外直接new续徽,所以我們要通過Builder來創(chuàng)建Retrofit對(duì)象
3、相關(guān)方法解析

由于create比較關(guān)鍵亲澡,我們最后解析

3.1钦扭、eagerlyValidateMethods方法解析
  private void eagerlyValidateMethods(Class<?> service) {
     //獲取平臺(tái)對(duì)象,安卓對(duì)象是Platform.Android
    Platform platform = Platform.get();
    //獲取service類的所有方法床绪,然后遍歷它的所有方法
    for (Method method : service.getDeclaredMethods()) {
      //由于Platform.Android沒有實(shí)現(xiàn)isDefaultMethod方法客情,所以默認(rèn)返回false
      if (!platform.isDefaultMethod(method)) {
        //調(diào)用loadServiceMethod()方法導(dǎo)入方法
        loadServiceMethod(method);
      }
    }
  }

具體流程如下:

  • 1、收取平臺(tái)對(duì)象
  • 2会涎、獲取所有類的所有方法裹匙,這里補(bǔ)充一個(gè)知識(shí)點(diǎn):getDeclaredMethods()方法返回的是類或接口聲明的所有方法,包括public末秃、protect、private籽御、默認(rèn)的方法练慕,但不包括它繼承的方法。當(dāng)然也包括它所有實(shí)現(xiàn)接口的方法技掏。getMethods()返回的是某個(gè)類的所有public的方法铃将,包括其繼承類的public方法,也包括實(shí)現(xiàn)接口的方法哑梳。
  • 3劲阎、遍歷這類的所有方法
  • 4、由于Platform.Android沒有重寫isDefaultMethod()鸠真,所以platform.isDefaultMethod(method)默認(rèn)返回false悯仙,Platform.Java8是重寫了這個(gè)方法的龄毡,大家有興趣的話可以去研究下。
  • 5锡垄、調(diào)用loadServiceMethod()方法

那么就讓我們研究下loadServiceMethod這個(gè)方法

3.2沦零、loadServiceMethod方法解析
  ServiceMethod<?, ?> loadServiceMethod(Method method) {
    //從緩沖中取出
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    //如果緩存中有,直接取出
    if (result != null) return result;
    //如果緩存中沒有货岭,加上同步鎖
    synchronized (serviceMethodCache) {
       //加上鎖后路操,為了保證實(shí)時(shí)性,再去一次
      result = serviceMethodCache.get(method);
      //如果還沒有
      if (result == null) {
        //直接構(gòu)建一個(gè)ServiceMethod.Builder對(duì)象千贯,然后調(diào)用ServiceMethod.Builder的builer方法構(gòu)建一個(gè)ServiceMethod對(duì)象關(guān)于build方法剛剛講過哦
        result = new ServiceMethod.Builder<>(this, method).build();
        把這個(gè)ServiceMethod 對(duì)象放入緩存中
        serviceMethodCache.put(method, result);
      }
    }
    //返回這個(gè)ServiceMethod 對(duì)象
    return result;
  }

其實(shí)看上面方法屯仗,其實(shí)就是一個(gè)一級(jí)緩存。先判斷緩存中有沒有搔谴,如果緩存中有魁袜,則直接返回,如果緩存沒有己沛,則獲取一個(gè)慌核,并添加到緩存中。

3.3申尼、callFactory()垮卓、baseUrl()、callAdapterFactories() 师幕、converterFactories()方法解析由于這四個(gè)方法比較簡(jiǎn)單粟按,其實(shí)就是get方法獲對(duì)應(yīng)的屬性,沒什么好說的霹粥,就簡(jiǎn)單貼下代碼灭将,大家看下就好。
  /**
   * The factory used to create {@linkplain okhttp3.Call OkHttp calls} for sending a HTTP requests.
   * Typically an instance of {@link OkHttpClient}.
   */
  public okhttp3.Call.Factory callFactory() {
    return callFactory;
  }

  /** The API base URL. */
  public HttpUrl baseUrl() {
    return baseUrl;
  }

  /**
   * Returns a list of the factories tried when creating a
   * {@linkplain #callAdapter(Type, Annotation[])} call adapter}.
   */
  public List<CallAdapter.Factory> callAdapterFactories() {
    return adapterFactories;
  }

  /**
   * Returns a list of the factories tried when creating a
   * {@linkplain #requestBodyConverter(Type, Annotation[], Annotation[]) request body converter}, a
   * {@linkplain #responseBodyConverter(Type, Annotation[]) response body converter}, or a
   * {@linkplain #stringConverter(Type, Annotation[]) string converter}.
   */
  public List<Converter.Factory> converterFactories() {
    return converterFactories;
  }
3.4后控、callAdapter() 方法解析

在上面ServiceMethod類中可是調(diào)用過這個(gè)方法的庙曙,大家還記得在哪里調(diào)用嗎?是在ServiceMethod類中createCallAdapter()方法里面最后return的時(shí)候調(diào)用了,那我們來看下源碼

  /**
   * Returns the {@link CallAdapter} for {@code returnType} from the available {@linkplain
   * #callAdapterFactories() factories}.
   *
   * @throws IllegalArgumentException if no call adapter available for {@code type}.
   */
  public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

通過方法注釋我們知道

從callAdapterFactories里面找到合適的CallAdapter浩淘,這個(gè)CallAdapter的返回值類型是returnType

大家看代碼捌朴,其實(shí)內(nèi)部調(diào)用的是nextCallAdapter()方法,那我們就來看下nextCallAdapter()方法

3.5张抄、nextCallAdapter()方法解析
  /**
   * Returns the {@link CallAdapter} for {@code returnType} from the available {@linkplain
   * #callAdapterFactories() factories} except {@code skipPast}.
   *
   * @throws IllegalArgumentException if no call adapter available for {@code type}.
   */
  public CallAdapter<?, ?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
     //非空判斷
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");
   //獲取skipPast的位置砂蔽,skpiPost屬于被拋棄的一方
    int start = adapterFactories.indexOf(skipPast) + 1;
    //如果skipPast是null,則start=-1,如果skipPast存在則從skipPast的下一個(gè)位置開始遍歷
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      //通過CallAdapter.Factory的get方法來獲取對(duì)應(yīng)的CallAdapter
      CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        //如果adapter不為null署惯,則返回adapter
        return adapter;
      }
    }
    // 如果遍歷了左驾,還是沒有合適的,則拋異常,下面只不過在拼接錯(cuò)誤信息
    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());
  }

先來看下方法的注釋:

除了skipPast(這個(gè)對(duì)象外)诡右,從callAdapterFactories里面再找一個(gè)返回類型是returnType的CallAdapter 對(duì)象

內(nèi)容很簡(jiǎn)單安岂,主要是遍歷callAdapterFactories里面,找到合適的CallAdapter稻爬,如果沒有則拋出異常嗜闻。

3.6、requestBodyConverter()方法解析
  /**
   * Returns a {@link Converter} for {@code type} to {@link RequestBody} from the available
   * {@linkplain #converterFactories() factories}.
   *
   * @throws IllegalArgumentException if no converter available for {@code type}.
   */
  public <T> Converter<T, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations) {
    return nextRequestBodyConverter(null, type, parameterAnnotations, methodAnnotations);
  }

從converterFactories里面找到一個(gè)合適的Converter桅锄,這個(gè)Converter的輸出類型是RequestBody琉雳。

其實(shí)內(nèi)部調(diào)用的是nextRequestBodyConverter,那我們看下這個(gè)nextRequestBodyConverter接口

3.7友瘤、nextRequestBodyConverter()方法解析
  /**
   * Returns a {@link Converter} for {@code type} to {@link RequestBody} from the available
   * {@linkplain #converterFactories() factories} except {@code skipPast}.
   *
   * @throws IllegalArgumentException if no converter available for {@code type}.
   */
  public <T> Converter<T, RequestBody> nextRequestBodyConverter(Converter.Factory skipPast,
      Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations) {
    //非空檢查
    checkNotNull(type, "type == null");
    checkNotNull(parameterAnnotations, "parameterAnnotations == null");
    checkNotNull(methodAnnotations, "methodAnnotations == null");
    //獲取被放棄的skipPast對(duì)象的位置翠肘,然后加1
    int start = converterFactories.indexOf(skipPast) + 1;
     //遍歷converterFactories
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      //獲取對(duì)應(yīng)的 Converter.Factory對(duì)象,然后調(diào)用requestBodyConverter()方法辫秧,
      Converter.Factory factory = converterFactories.get(i);
      Converter<?, RequestBody> converter =
          factory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, this);
      //由于requestBodyConverter()默認(rèn)是返回null束倍,所以只有重寫過才會(huì)不為null
      if (converter != null) {
        //noinspection unchecked
        return (Converter<T, RequestBody>) converter;
      }
    }
   // 如果遍歷了,還是沒有合適的盟戏,則拋異常绪妹,下面只不過在拼接錯(cuò)誤信息
    StringBuilder builder = new StringBuilder("Could not locate RequestBody 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());
  }

先來說下方法的注釋

除了skipPast(這個(gè)對(duì)象外),從converterFactories里面再找輸出類型是RequestBody的converter 對(duì)象

內(nèi)容很簡(jiǎn)單

有點(diǎn)類似于nextCallAdapter()柿究,主要是遍歷converterFactories邮旷,找到合適的converter,如果沒有則拋出異常蝇摸。

3.8婶肩、responseBodyConverter()方法解析
  /**
   * Returns a {@link Converter} for {@link ResponseBody} to {@code type} from the available
   * {@linkplain #converterFactories() factories}.
   *
   * @throws IllegalArgumentException if no converter available for {@code type}.
   */
  public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
  }

先看下方法的注釋

從converterFactories里面找到一個(gè)合適的Converter,這個(gè)Converter的輸如類型是ResponseBody貌夕。

其實(shí)內(nèi)部調(diào)用時(shí)的nextResponseBodyConverter()律歼,那我們來看下nextResponseBodyConverter()的具體實(shí)現(xiàn)。

3.9啡专、nextResponseBodyConverter()方法解析
  /**
   * Returns a {@link Converter} for {@link ResponseBody} to {@code type} from the available
   * {@linkplain #converterFactories() factories} except {@code skipPast}.
   *
   * @throws IllegalArgumentException if no converter available for {@code type}.
   */
  public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
      Type type, Annotation[] annotations) {
     //非空判斷
    checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");
    //獲取被放棄的skipPast的位置险毁,如果是null則是-1
    int start = converterFactories.indexOf(skipPast) + 1;
    //遍歷converterFactories
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      //通過responseBodyConverter()來獲取一個(gè)輸入是ResponseBody的Converter
      Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
       //如果Converter不為null,則說明找到了
      if (converter != null) {
        //noinspection unchecked
        return (Converter<ResponseBody, T>) converter;
      }
    }
 // 如果遍歷了们童,還是沒有合適的辱揭,則拋異常,下面只不過在拼接錯(cuò)誤信息
    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());
  }

先看下注釋

除了skipPast(這個(gè)對(duì)象外)病附,從converterFactories里面再找一個(gè)輸入類型是ResponseBody的Converter 對(duì)象

通過閱讀源碼,我們發(fā)現(xiàn):

有點(diǎn)類似于nextRequestBodyConverter()亥鬓,主要是遍歷converterFactories完沪,找到合適的converter,如果沒有則拋出異常。

3.10覆积、stringConverter()方法解析
  /**
   * Returns a {@link Converter} for {@code type} to {@link String} from the available
   * {@linkplain #converterFactories() factories}.
   */
  public <T> Converter<T, String> stringConverter(Type type, Annotation[] annotations) {
     //非空判斷
    checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");
    //獲取對(duì)應(yīng)的 Converter.Factory對(duì)象
    for (int i = 0, count = converterFactories.size(); i < count; i++) {
       //然后調(diào)用stringConverter()方法獲取對(duì)應(yīng)的Converter對(duì)象
      Converter<?, String> converter =
          converterFactories.get(i).stringConverter(type, annotations, this);
       //非空判斷听皿,因?yàn)槿绻也坏剑瑒t返回null
      if (converter != null) {
        //noinspection unchecked
        return (Converter<T, String>) converter;
      }
    }
 // 如果遍歷了宽档,還是沒有合適的尉姨,調(diào)用默認(rèn)的轉(zhuǎn)換器的toString()方法,默認(rèn)的轉(zhuǎn)換器是BuiltInConverters
    // Nothing matched. Resort to default converter which just calls toString().
    //noinspection unchecked
    return (Converter<T, String>) BuiltInConverters.ToStringConverter.INSTANCE;
  }

先來看下方法的注釋吗冤,翻譯一下:

從converterFactories里面找到一個(gè)合適的Converter又厉,這個(gè)Converter的輸出類型是RequestBody。

實(shí)際內(nèi)容也很簡(jiǎn)單椎瘟,遍歷converterFactories覆致。獲取Converter.Factory對(duì)象,調(diào)用這個(gè)對(duì)象的stringConverter()來獲取Converter對(duì)象肺蔚,如果Converter不為空煌妈,則證明取到了,如果沒有取到宣羊,則調(diào)用默認(rèn)的轉(zhuǎn)化器來轉(zhuǎn)化璧诵。

3.11、callbackExecutor()方法解析
  /**
   * The executor used for {@link Callback} methods on a {@link Call}. This may be {@code null},
   * in which case callbacks should be made synchronously on the background thread.
   */
  public Executor callbackExecutor() {
    return callbackExecutor;
  }

先翻譯一下

這個(gè)線程池被用來執(zhí)行一個(gè)請(qǐng)求的回調(diào)仇冯,在這種情況下之宿,回調(diào)應(yīng)該在后臺(tái)線程上同步進(jìn)行。

其實(shí)就會(huì)返回回調(diào)的線程池

3.12赞枕、newBuilder()方法解析

代碼很簡(jiǎn)單澈缺,就是new一個(gè)Builder對(duì)象并返回

  public Builder newBuilder() {
    return new Builder(this);
  }

(三) 靜態(tài)內(nèi)部類Builder解析

1、老規(guī)矩先來看下類的注釋
  /**
   * Build a new {@link Retrofit}.
   * <p>
   * Calling {@link #baseUrl} is required before calling {@link #build()}. All other methods
   * are optional.
   */

翻譯一下:

通過調(diào)用一個(gè)build()方法來構(gòu)建一個(gè)Retrofit對(duì)象炕婶,在build()之前需要調(diào)用baseUrl()方法姐赡,所有其他方法都是可選的。

2柠掂、看下變量

變量不多项滑,我直接上注釋了

    //平臺(tái)
    private final Platform platform;
    //okhttp3的callFactory
    private okhttp3.Call.Factory callFactory;
     //HttpUrl
    private HttpUrl baseUrl;
    //converterFactories集合
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    //adapterFactories 集合
    private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
    //回調(diào)線程池
    private Executor callbackExecutor;
     //是否需要提前檢查的布爾變量
    private boolean validateEagerly;

通過上述代碼我們可以得出以下信息

  • 1、converterFactories和adapterFactories一定是不為null的
  • 2涯贞、platform是final的枪狂,初始化的時(shí)候一定要賦值的
3、構(gòu)造函數(shù)

Builder有三個(gè)構(gòu)造函數(shù)宋渔,一個(gè)是無參的public州疾,兩個(gè)是包內(nèi)的,所以皇拣,外部調(diào)用一定是new無參的構(gòu)造函數(shù)

    Builder(Platform platform) {
      this.platform = platform;
      // 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());
    }
    public Builder() {
      this(Platform.get());
    }

    Builder(Retrofit retrofit) {
      platform = Platform.get();
      callFactory = retrofit.callFactory;
      baseUrl = retrofit.baseUrl;
      converterFactories.addAll(retrofit.converterFactories);
      adapterFactories.addAll(retrofit.adapterFactories);
      // Remove the default, platform-aware call adapter added by build().
      adapterFactories.remove(adapterFactories.size() - 1);
      callbackExecutor = retrofit.callbackExecutor;
      validateEagerly = retrofit.validateEagerly;
    }
  • 1严蓖、無參數(shù)的構(gòu)造函數(shù)其實(shí)內(nèi)部調(diào)用的是入?yún)⑹荘latform的構(gòu)造函數(shù)薄嫡,Platform.get()方法我們前面已經(jīng)說過了,返回的是Android對(duì)象
  • 2颗胡、入?yún)⑹莗latform的構(gòu)造函數(shù)毫深,內(nèi)部add了一個(gè)BuiltInConverters對(duì)象,可見converterFactories至少是一個(gè)轉(zhuǎn)化器的毒姨。
  • 3哑蔫、入?yún)⒌氖荝etrofit的構(gòu)造函數(shù),其實(shí)就是把Retrofit的屬性賦值給Builder
4弧呐、相關(guān)方法解析
4.1闸迷、client方法和callFactory
    /**
     * The HTTP client used for requests.
     * <p>
     * This is a convenience method for calling {@link #callFactory}.
     * 通過callFactory作為客戶端,來發(fā)起HTTP請(qǐng)求是非常便捷的泉懦。
     */
    public Builder client(OkHttpClient client) {
      return callFactory(checkNotNull(client, "client == null"));
    }

    /**
     * Specify a custom call factory for creating {@link Call} instances.
     * <p>
     * Note: Calling {@link #client} automatically sets this value.
     * 通過自定義的call factory  來創(chuàng)建一個(gè)請(qǐng)求(Call)的實(shí)例稿黍,調(diào)用client會(huì)自動(dòng)設(shè)置
     */
    public Builder callFactory(okhttp3.Call.Factory factory) {
      this.callFactory = checkNotNull(factory, "factory == null");
      return this;
    }

通過上面我們可知

  • client內(nèi)部調(diào)用的callFactory方法
  • 這兩個(gè)方法表明,Retrofit底層是使用okHttp崩哩,而且是強(qiáng)關(guān)聯(lián)巡球。
  • PS:第一次看代碼的哥們可能會(huì)有疑惑,這里補(bǔ)充下OkHttpClient是okhttp3.Call.Factory的實(shí)現(xiàn)類邓嘹。
4.2酣栈、baseUrl方法

Builder有兩個(gè)baseUrl,只不過是入?yún)⒉煌研谘海屛覀儊砜聪略创a

 /**
     * Set the API base URL.
     *
     * @see #baseUrl(HttpUrl)
     */
    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);
    }

    //收到篇幅限制矿筝,注釋太長(zhǎng)我直接省略
    public Builder baseUrl(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);
      }
      this.baseUrl = baseUrl;
      return this;
    }
  • 主要是設(shè)置基本的url,一般是請(qǐng)求的url的前綴
  • 受篇幅限制棚贾,我這邊沒有粘貼注釋窖维,不過注釋非常不錯(cuò),我建議大家還是去看看妙痹,里面主要講解拼接的注意事件铸史。
4.3、addConverterFactory()和addCallAdapterFactory方法
    /** Add converter factory for serialization and deserialization of objects. */
    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

    /**
     * Add a call adapter factory for supporting service method return types other than {@link
     * Call}.
     */
    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

addConverterFactory()和addCallAdapterFactory方法比較簡(jiǎn)單怯伊,就是向?qū)?yīng)的集合添加元素而已

4.4琳轿、callbackExecutor()和validateEagerly方法
    /**
     * The executor on which {@link Callback} methods are invoked when returning {@link Call} from
     * your service method.
     * <p>
     * Note: {@code executor} is not used for {@linkplain #addCallAdapterFactory custom method
     * return types}.
     */
    public Builder callbackExecutor(Executor executor) {
      this.callbackExecutor = checkNotNull(executor, "executor == null");
      return this;
    }

    /**
     * When calling {@link #create} on the resulting {@link Retrofit} instance, eagerly validate
     * the configuration of all methods in the supplied interface.
     */
    public Builder validateEagerly(boolean validateEagerly) {
      this.validateEagerly = validateEagerly;
      return this;
    }

這兩個(gè)方法也比較簡(jiǎn)單,就是給兩個(gè)變量賦值

4.5耿芹、build()方法
    /**
     * Create the {@link Retrofit} instance using the configured values.
     * <p>
     * Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
     * OkHttpClient} will be created and used.
     */
    public Retrofit build() {
       //如果沒有配置過baseUrl崭篡,則拋異常
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      //獲取callFactory
      okhttp3.Call.Factory callFactory = this.callFactory;
      //如果為null,則沒有調(diào)用過client()和callFactory()方法
      if (callFactory == null) {
        //創(chuàng)建一個(gè)OkHttpClient對(duì)象,作為默認(rèn)的callFactory
        callFactory = new OkHttpClient();
      }
      //獲取回調(diào)的線程池
      Executor callbackExecutor = this.callbackExecutor;
      // 如果callbackExecutor為null,則沒有設(shè)置過回調(diào)線程池吧秕,
      if (callbackExecutor == null) {
        //獲取平臺(tái)默認(rèn)的線程池琉闪,其實(shí)就是主線程
        callbackExecutor = platform.defaultCallbackExecutor();
      }
      // Make a defensive copy of the adapters and add the default Call adapter.
     // 給adapterFactories賦值
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);     
      //添加一個(gè)默認(rèn)的callAdapter,其實(shí)是DefaultCallAdapterFactory
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
      // Make a defensive copy of the converters.
       // 設(shè)置converterFactories砸彬,它默認(rèn)是含有BuiltInConverters對(duì)象的
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
      //構(gòu)建一個(gè)Retrofit對(duì)象
      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }

先看下注釋

通知使用配置過的值來創(chuàng)建Retrofit對(duì)象塘偎,如果沒有調(diào)用client()和callFactory()方法疗涉,那么將創(chuàng)建并使用默認(rèn)的OkHttpClient。

代碼很簡(jiǎn)單吟秩,就是初始化屬性,這里重點(diǎn)說下绽淘,如果沒有設(shè)置回調(diào)線程池涵防,則默認(rèn)是主線程,如果沒有配置轉(zhuǎn)化器沪铭,則默認(rèn)使用BuiltInConverters壮池,如果沒配置callAdapter,則默認(rèn)使用DefaultCallAdapterFactory杀怠。

(四) create()方法解析

這個(gè)方法很重要椰憋,由于受到篇幅限制,我就不粘貼注釋的了赔退,我們先來看下源碼

  @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
  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.
            //如果定義方法的類的類型是Object橙依,或者說,是Object類的方法硕旗,則直接執(zhí)行invoke調(diào)用
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            // Android平臺(tái)沒有重寫這個(gè)方法窗骑,所以默認(rèn)是false
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
             //調(diào)用loadServiceMethod獲取一個(gè)ServiceMethod對(duì)象,其內(nèi)部是一個(gè)一級(jí)緩存漆枚,內(nèi)存中有直接取內(nèi)存中的创译,內(nèi)存中沒有構(gòu)建一個(gè)ServiceMethod,放入到緩存中墙基。
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            //使用serviceMethod和args來構(gòu)建一個(gè)OkHttpCall
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //調(diào)用serviceMethod對(duì)象的callAdapter對(duì)象的adapt方法软族。
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

通過源碼我們知道,這方法內(nèi)部的流程如下:

  • 檢查 接口類残制,判斷是否是接口立砸,判斷是否繼承其他接口
  • 做是否需要預(yù)加載
  • 調(diào)用動(dòng)態(tài)代理獲取一個(gè)類的對(duì)象

然后我們看下InvocationHandler里面的invoke()方法里面的實(shí)現(xiàn)流程

  • 先判斷這個(gè)方法是不是Object的方法,如果是直接接調(diào)用invoke
  • 根據(jù)平臺(tái)的特性痘拆,決定是否調(diào)用invokeDefaultMethod()方法
  • 通過調(diào)用loadServiceMethod()方法載入一個(gè)ServiceMethod對(duì)象仰禽。
  • 用ServiceMethod來構(gòu)建一個(gè)OkHttpCall。
  • 最后調(diào)用serviceMethod對(duì)象的callAdapter對(duì)象的adapt方法

最后翻譯了一下這個(gè)方法對(duì)應(yīng)的注釋纺蛆,受篇幅限制吐葵,我就不粘貼源碼了,直接上我們翻譯后的內(nèi)容了

創(chuàng)建一個(gè)由服務(wù)器定義的API接口的具體實(shí)現(xiàn)桥氏。如果在抽象接口的方法上通過添加注解來實(shí)現(xiàn)設(shè)置定義請(qǐng)求方式温峭,而相對(duì)路徑的url是根據(jù)這個(gè)請(qǐng)求方式來的。請(qǐng)求方式有@link retrofit2.http.GET 代表GET請(qǐng)求字支,@link retrofit2.http.PUT 代表PUT請(qǐng)求凤藏,@retrofit2.http.POST奸忽,代表POST請(qǐng)求,@retrofit2.http.PATCH 代表PATCH請(qǐng)求揖庄,@retrofit2.http.HEAD 代表HEAD請(qǐng)求栗菜,
@retrofit2.http.DELETE 代表DELETE請(qǐng)求, @retrofit2.http.OPTIONS 代表OPTIONS請(qǐng)求蹄梢,通過使用@HTTP疙筹,你也可以自定義HTTP請(qǐng)求方式。如果你想動(dòng)態(tài)設(shè)置url禁炒,第一個(gè)入?yún)⑿枰褂聾Url 注解來實(shí)現(xiàn)檀夹』冢可以在方法參數(shù)里面使用@Path注解,是實(shí)現(xiàn)替換Url部分內(nèi)容,被替換的部分需要用大括號(hào)“{}”括起來督赤,例如"{foo}"陕凹。如果想在URL上添加查詢字段树碱,就要使用@Query 注解记罚。用@ Body 來表示一個(gè)請(qǐng)求體。一個(gè)對(duì)象的實(shí)例將會(huì)被Converter.Factory的實(shí)例轉(zhuǎn)化為網(wǎng)絡(luò)請(qǐng)求玛痊。一個(gè)RequestBody也可以作為原始數(shù)據(jù)而直接使用汰瘫。方法注解和參數(shù)注解支持如下的格式:通過@FormUrlEncoded,代表表單提交擂煞,由@Field注解 代表表單數(shù)據(jù)混弥。@multipart 代表多部分,在入?yún)⑸鲜褂米⒔釦Part表示每一部分的具體數(shù)據(jù)对省。通過在方法上添加@Header 和@Header來添加請(qǐng)求頭的數(shù)據(jù)蝗拿。默認(rèn)情況下,這個(gè)方法返回一個(gè)代表HTTP請(qǐng)求的Call對(duì)象蒿涎,里面的泛型是響應(yīng)體的類型哀托,由 Converter.Factory對(duì)象負(fù)責(zé)轉(zhuǎn)化,也可以用ResponseBody代表原始數(shù)據(jù)劳秋,當(dāng)然你不關(guān)心請(qǐng)求體仓手,也可以設(shè)置Void。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末玻淑,一起剝皮案震驚了整個(gè)濱河市嗽冒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌补履,老刑警劉巖添坊,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異箫锤,居然都是意外死亡贬蛙,警方通過查閱死者的電腦和手機(jī)雨女,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阳准,“玉大人氛堕,你說我怎么就攤上這事∧缰埃” “怎么了岔擂?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)浪耘。 經(jīng)常有香客問我,道長(zhǎng)塑崖,這世上最難降的妖魔是什么七冲? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮规婆,結(jié)果婚禮上澜躺,老公的妹妹穿的比我還像新娘。我一直安慰自己抒蚜,他們只是感情好掘鄙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嗡髓,像睡著了一般操漠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上饿这,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天浊伙,我揣著相機(jī)與錄音,去河邊找鬼长捧。 笑死嚣鄙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的串结。 我是一名探鬼主播哑子,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼肌割!你這毒婦竟也來了卧蜓?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤声功,失蹤者是張志新(化名)和其女友劉穎烦却,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體先巴,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡其爵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年冒冬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摩渺。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡简烤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出摇幻,到底是詐尸還是另有隱情横侦,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布绰姻,位于F島的核電站枉侧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏狂芋。R本人自食惡果不足惜榨馁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望帜矾。 院中可真熱鬧翼虫,春花似錦、人聲如沸屡萤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽死陆。三九已至招拙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間翔曲,已是汗流浹背迫像。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞳遍,地道東北人闻妓。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像掠械,于是被迫代替她去往敵國(guó)和親由缆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容