Android小知识-剖析Retrofit中的网络请求接口

672 阅读4分钟

本平台的文章更新会有延迟,大家可以关注微信公众号-顾林海,包括年底前会更新kotlin由浅入深系列教程,目前计划在微信公众号进行首发,如果大家想获取最新教程,请关注微信公众号,谢谢!

在前两节《Android小知识-剖析Retrofit中静态内部类Builder的三个方法》和《Android小知识-剖析Retrofit中的网络请求流程以及相关参数

》中介绍了一些成员变量的初始化工作,那么本节就来介绍剖析Retrofit中的网络请求接口。

public interface NetworkInterface {
    @GET("news/newsDetail")
    Call<MyResponse> getNewsDetails(@QueryMap Map<String,String> map);
}

进行网络请求前需要创建网络请求接口类,在上面定义为NetworkInterface接口,其中定义了一个接受网络请求数据的方法叫做getNewsDetail,返回类型是一个泛型Call,Call里面的类型是MyResponse,MyResponse就是我们请求网络返回的数据类型,在getNewsDetail方法上添加了注解GET,表示网络请求是用GET方式来请求的,在注解GET中定义相对url地址,在Retrofit中,网络请求的URL分为两部分,第一部分在创建Retrofit时通过baseUrl传入http请求的基地址,第二部分就是上面注解GET后面定义的http请求的相对地址,两者加起来就是完整的http请求地址。

  private void initRetrofit() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://icould.glh/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

        NetworkInterface networkInterface = retrofit.create(NetworkInterface.class);
}

创建完网络请求接口后就可以通过Retrofit的create方法,把网络请求接口的Class对象传递进去,返回一个网络请求接口的代理类。

进入create方法:

  public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    ...
}

通过工具类Utils的validateServiceInterface方法对接口的字节码进行验证,下面判断validateEagerly标志位,在《Android小知识-剖析Retrofit中的网络请求流程以及相关参数》介绍过这个标志位,表示是否提前解析网络请求接口中的方法,如果validateEagerly为true,就会执行eagerlyValidateMethods方法。

进入eagerlyValidateMethods方法:

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

在该方法先是获取具体的平台Platform,往下看是一个for循环,通过反射获取网络请求接口中的方法并遍历,在遍历时判断isDefaultMethod方法。

    boolean isDefaultMethod(Method method) {
    return false;
  }

发现isDefaultMethod方法固定返回false,那么上面的if判断语句中就会执行loadServiceMethod方法。

进入loadServiceMethod方法:

    private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
        ...
    }

loadServiceMethod方法返回一个ServiceMethod对象,在Retrofit中通过动态代理的方式将网络请求接口中的方法转换成一个个http请求,这个ServiceMethod对象就是对应接口中的一个方法,对接口中的方法进行封装。

    private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
    ServiceMethod<?, ?> loadServiceMethod(Method method) {

        ServiceMethod<?, ?> result = serviceMethodCache.get(method);
        if (result != null) return result;

        ...
    }

在loadServiceMethod方法中一开始从serviceMethodCache集合获取请求方法对应的ServiceMethod对象,serviceMethodCache是ConcurrentHashMap集合类型,是线程安全的Map集合,如果serviceMethodCache当中存在对应请求方法的ServiceMethod对象,就直接返回该对象。

    private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
    ServiceMethod<?, ?> loadServiceMethod(Method method) {
        ...
        synchronized (serviceMethodCache) {
            result = serviceMethodCache.get(method);
            if (result == null) {
                result = new ServiceMethod.Builder<>(this, method).build();
                serviceMethodCache.put(method, result);
            }
        }
        return result;
    }

如果serviceMethodCache这个缓存集合中没有对应方法的ServiceMethod对象,那么就会利用Builder模式重新创建ServiceMethod对象,并将这个ServiceMethod对象保存在serviceMethodCache这个缓存集合中。

继续回到Retrofit的create方法中:

    public <T> T create(final Class<T> service) {
        ...
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
                new InvocationHandler() {
                    private final Platform platform = Platform.get();

                    @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
                            throws Throwable {
                        ...
                        ServiceMethod<Object, Object> serviceMethod =
                                (ServiceMethod<Object, Object>) loadServiceMethod(method);
                        OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                        return serviceMethod.adapt(okHttpCall);
                    }
                });
    }

可以看到create方法返回的是网络请求接口的动态代理对象,通过Proxy的newProxyInstance方法创建动态代理对象,当我们调用代理类方法时,就会执行InvocationHandler的invoke方法。

整个Retrofit的核心就是InvocationHandler的invoke方法中的三行代码,后面一节会对这三个核心代码进行讲解。


838794-506ddad529df4cd4.webp.jpg

搜索微信“顾林海”公众号,定期推送优质文章。