android之Retrofit2原理解析

1.前言

Retrofit2框架是对请求的封装,请求框架使用OKhttp框架,本篇不分析OKhttp框架,只分析Retrofit2框架如何将Java接口通过动态代理生成一个个的请求对象。

2.Retrofit2使用

//retrofit2包引用
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
/**
 * Retrofit工具测试类
 *
 * @author zhukui
 */
public abstract class RetrofitUtil {

    /**
     * 用户相关请求
     */
    public interface IUserRequest {
        @GET("userInfo/{userId}/")
        Call<List<String>> getUserInfo(@Path("userId") String userId);
    }

    /**
     * 测试方法
     */
    private void test() {
        //Retrofit对象创建,这里用的是建造者模式创建
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .build();

        //动态代理生成请求对象,并用接口多态
        IUserRequest service = retrofit.create(IUserRequest.class);

        //请求对象
        Call<List<String>> request = service.getUserInfo("10086");

        //同步请求
        try {
            Response<List<String>> response = request.execute();
            List<String> list = response.body();
        } catch (Exception e) {
            e.printStackTrace();
        }

        //异步请求
        request.enqueue(new Callback<List<String>>() {
            @Override
            public void onResponse(Call<List<String>> call, Response<List<String>> response) {
                List<String> list = response.body();
            }

            @Override
            public void onFailure(Call<List<String>> call, Throwable t) {
                t.printStackTrace();
            }
        });
    }
    
}

3.Retrofit2源码分析

1.Retrofit对象创建

主要基于建造者模式创建,baseUrl()为主要方法。IUserRequest为用户类请求接口,getUserInfo为模拟获取用户信息接口,接口注解及接口参数配置可查看Retrofit官网说明,不是本篇侧重点,这里继续往下。

2.retrofit.create方法 - 重点

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();
          private final Object[] emptyArgs = new Object[0];

          @Override public @Nullable 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);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }
Utils.validateServiceInterface(service)判断是否是interface接口,如果这里是普通Java类型会直接抛出异常。
if (validateEagerly) { eagerlyValidateMethods(service);} 这里可以设置是否缓存接口解析,非重点直接下一步
Proxy.newProxyInstance这是调用java的动态代理生成了代理类。
 public static Object newProxyInstance(ClassLoader loader,
                                       Class<?>[] interfaces,
                                       InvocationHandler h)

loader: 用哪个类加载器去加载代理对象

interfaces:动态代理类需要实现的接口

h:动态代理方法在执行时,会调用h里面的invoke方法去执行

 Proxy.newProxyInstance程序运行时产生一个类$proxy0

$proxy0类继承自Proxy类,实现了目标对象的父类接口(借鉴的百度提供的源码)

$proxy0类有多个Method成员变量,它的静态代码块给Method赋值为我们自己的接口的实现类的对应的Method对象

$proxy0实现接口的方法调用了super.h.invoke(参数),这里的参数包括Method变量

//$proxy0的源码
public final class $Proxy0 extends Proxy implements Subject {  
    private static Method m1;  
    private static Method m0;  
    private static Method m3;  
    private static Method m2;  
  
    static {  
        try {  
            m1 = Class.forName("java.lang.Object").getMethod("equals",  
                    new Class[] { Class.forName("java.lang.Object") });  
  
            m0 = Class.forName("java.lang.Object").getMethod("hashCode",  
                    new Class[0]);  
  
            m3 = Class.forName("接口的实现类的路径").getMethod("实现类的方法",  
                    new Class[0]);  
  
            m2 = Class.forName("java.lang.Object").getMethod("toString",  
                    new Class[0]);  
  
        } catch (NoSuchMethodException nosuchmethodexception) {  
            throw new NoSuchMethodError(nosuchmethodexception.getMessage());  
        } catch (ClassNotFoundException classnotfoundexception) {  
            throw new NoClassDefFoundError(classnotfoundexception.getMessage());  
        }  
    } //static  
  
    public $Proxy0(InvocationHandler invocationhandler) {  
        super(invocationhandler);  
    }  
  
    @Override  
    public final boolean equals(Object obj) {  
        try {  
            return ((Boolean) super.h.invoke(this, m1, new Object[] { obj })) .booleanValue();  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
  
    @Override  
    public final int hashCode() {  
        try {  
            return ((Integer) super.h.invoke(this, m0, null)).intValue();  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
  
    public final void 接口的实现类的方法() {  
        try {  
            super.h.invoke(this, m3, null);  
            return;  
        } catch (Error e) {  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
  
    @Override  
    public final String toString() {  
        try {  
            return (String) super.h.invoke(this, m2, null);  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
}  

代理对象调接口中的方法---代理对象的真身是$proxy0 调用了对应的方法---此方法内部调用其父类的成员h调用h的invoke方法---就是调用传入了InvocationHandler的invoke方法,至于返回值,那就看我们的InvocationHandler的invoke方法怎么写。这里Retrofit2重写了invoke方法返回值,实际为每个返回值为Call的方法返回了OkHttpCall对象。

3.loadServiceMethod分析

loadServiceMethod(method).invoke(args != null ? args : emptyArgs);

private final Map<Method, ServiceMethod<?>> 
                          serviceMethodCache = new ConcurrentHashMap<>();
 
ServiceMethod<?> loadServiceMethod(Method method) {
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

我们继续看ServiceMethod.parseAnnotations方法。

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(method,
          "Method return type must not include a type variable or wildcard: %s", returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract @Nullable T invoke(Object[] args);
}

ServiceMethod.parseAnnotations方法中RequestFactory.parseAnnotations()中进行方法注解、方法参数、方法参数注解等处理,并且负责创建请求时拼接resultful格式。

        @GET("userInfo/{userId}/")
        Call<List<String>> getUserInfo(@Path("userId") String userId);

这里userId传的是"10086",会将userId值赋值到login/{userId}/中,即拼接为/userInfo/10086,

根据 baseUrl配置,最终 请求地址+请求参数 结果 :

baseUrl = https://api.github.com

relativeUrl = /userInfo/10086

最终请求为:https://api.github.com/userInfo/10086

private final HttpUrl baseUrl;
private @Nullable String relativeUrl;

static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
}


//这里处理方法,方法上的注解,参数类型,参数注解
Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();
      this.parameterTypes = method.getGenericParameterTypes();
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }


RequestFactory build() {
      for (Annotation annotation : methodAnnotations) {
        //解析方法注解
        parseMethodAnnotation(annotation);
      }
      //......
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) 
      {
        parameterHandlers[p] =
            //解析参数
            parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == 
            lastParameter);
      }
      //......
      return new RequestFactory(this);
 }

//解析参数
ParameterHandler<?> parseParameter(
        int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
         //.....
         //解析参数注解
         parseParameterAnnotation(p, parameterType, annotations, annotation);

        Path path = (Path) annotation;
        String name = path.value();
        validatePathName(p, name);
         //.....
    }


//解析参数注解
@Nullable
private ParameterHandler<?> parseParameterAnnotation(
        int p, Type type, Annotation[] annotations, Annotation annotation) {
     //.....
        //处理参数注解Path
        Path path = (Path) annotation;
        String name = path.value();
        validatePathName(p, name);
     //.....
}


//创建请求
okhttp3.Request create(Object[] args) throws IOException {
 //.....
}


继续看return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {

  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {

      //...

      return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
          callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
          continuationBodyNullable);
}

 @Override final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }
}



 static final class SuspendForBody<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
    private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;
    private final boolean isNullable;

     //...
}

可以看到 HttpServiceMethod是ServiceMethod子类,最终返回的SuspendForBody也是ServiceMethod子类,到这里就可以看到上面invoke方法的最终实现。

4.invoke方法

 @Override final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }

我们可以看到此处new OkHttpCall()对象,并且传了requestFactory等必要的请求参数,这里就将每一个方法翻译成了一个个请求。

上一篇:IDEA:public static void main(String[] args)创立等常用快捷键


下一篇:方法:Demo3_CommandLine