美文网首页
Retrofit注解的理解

Retrofit注解的理解

作者: Seachal | 来源:发表于2019-05-07 14:27 被阅读0次

    Retrofit使用注解,使网络请求的代码特别简洁,但是内部是怎样通过注解转换成一个正常格式的网络请求链接的呢?
    阅读源码理解如下:

    POST注解

      /**
         * 登录
         *
         * @return
         */
        @POST("service-auth/login")
        Observable<Result> login(@Query("userPhone") String userPhone, @Query("userPwd") String userPwd);
    

    点击POST看看他是什么

    /** Make a POST request. */
    @Documented
    @Target(METHOD)
    @Retention(RUNTIME)
    public @interface POST {
      /**
       * A relative or absolute path, or full URL of the endpoint. This value is optional if the first
       * parameter of the method is annotated with {@link Url @Url}.
       * <p>
       * See {@linkplain retrofit2.Retrofit.Builder#baseUrl(HttpUrl) base URL} for details of how
       * this is resolved against a base URL to create the full endpoint URL.
       */
      String value() default "";
    }
    

    @Target(METHOD)说明这是一个方法注解
    @Retention(RUNTIME) 表示需要在什么级别保存该注解信息

    然后我们找找POST注解在哪使用了:
    ServiceMethod

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

    发现在ServiceMethod中被使用了。


    image.png

    ServiceMethod

    public ServiceMethod build() {
    ...
      for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);
          }
    ...
        }
    

    ServiceMethod

    Builder(Retrofit retrofit, Method method) {
          this.retrofit = retrofit;
          this.method = method;
          this.methodAnnotations = method.getAnnotations();
          this.parameterTypes = method.getGenericParameterTypes();
          this.parameterAnnotationsArray = method.getParameterAnnotations();
        }
    

    Retrofit

      ServiceMethod<?, ?> loadServiceMethod(Method method) {
       ...
            result = new ServiceMethod.Builder<>(this, method).build();
           ...
      }
    

    Retrofit

      private void eagerlyValidateMethods(Class<?> service) {
        Platform platform = Platform.get();
        for (Method method : service.getDeclaredMethods()) {
          if (!platform.isDefaultMethod(method)) {
            loadServiceMethod(method);
          }
        }
      }
    

    整个过程从上到下是,1.传给eagerlyValidateMethods一个Class对象,
    2.通过反射 service.getDeclaredMethods()从Class的得到Method,
    3.this.methodAnnotations = method.getAnnotations();从Method获得方法的注解,4.在 parseMethodAnnotation中根据获取的注解做分支操作。

    使用时,在

    ServiceFactory.getInstance()
                    .createService(AccountService.class)
                    .login(userCode, pwd);
    

    被执行时,注解修饰的interface login()方法

      /**
         * 登录
         *
         * @return
         */
        @POST("service-auth/login")
        Observable<Result> login(@Query("userPhone") String userPhone, @Query("userPwd") String userPwd);
    

    就被转化为post 请求形式。

    curl -X POST "http://xxx.service-auth/login?userPhone=1&userPwd=1" -H "accept: */*" -H "token: 1"
    

    参考: 对注解的使用,和自定义注解有一定的了解后,会更容易理解理解Retrofit的注解。

    相关文章

      网友评论

          本文标题:Retrofit注解的理解

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