Retrofit(一)

318 阅读4分钟

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

前面介绍了okHttp以及常用的加密方式

okHttp总结(一)

okHttp总结(二)

Java开发中常用的加密方式

这里主要讲Retrofit的用法

一、简介

Retrofit简单的总结就是通过动态代理的方式将Java接口翻译成网络请求,通过OkHttp发送请求,并且支持各种数据格式的转换

二、使用

1. 添加依赖

2. 定义接口类

public interface TranslateApi {
    @POST("ajax.php?a=fy&f=auto&t=auto")
    @FormUrlEncoded
    Call<TranslateBean> translateRequest(@Field("w") String input);
}

3. 创建Retrofit实例

通过Builder模式构造一个Retrofit对象

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://fy.iciba.com/") // 配置HOST
    // 添加解读返回数据的对象,因为返回数据是Json格式的,所以这里采用GsonConverterFactory来解读
    .addConverterFactory(GsonConverterFactory.create())
    // 添加适配OkHttpCall对象的CallAdapterFactory
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build();

4. 生成具体的请求实体对象

5. 调用Call对象的enqueue方法发起异步网络请求

6. 总结

首先我们定义了网络请求的接口,接口中配置了请求的基本信息,包括请求方法、请求参数等;接着我们生成了一个Retrofit对象,在这里可以配置请求的默认Host信息、添加解析返回数据格式的Factory、添加适配OkHttpCall的Factory等功能;然后调用retrofit对象的create方法,传入网络请求接口类,生成一个具体的网络请求实体对象;接下来我们调用了请求方法生成一个能够发起网络请求的Call对象,最后调用Call对象的enquene方法将发起异步的网络请求,并且在传入的Callback中处理网络请求的回调

二、原理分析

Retrofit核心是根据接口生成一个能够发起网络请求的对象,然后根据这个对象再发起网络请求

1. Retrofit

public Retrofit build() {
  if (baseUrl == null) {
    throw new IllegalStateException("Base URL required.");
  }
  okhttp3.Call.Factory callFactory = this.callFactory;
  if (callFactory == null) {
    // 如果没有设置网络请求框架,模式使用OkHttp处理网络请求
    callFactory = new OkHttpClient(); 
  }
  Executor callbackExecutor = this.callbackExecutor;
  if (callbackExecutor == null) {
    // 默认使用platform.defaultCallbackExecutor()处理返回结果
    callbackExecutor = platform.defaultCallbackExecutor(); 
  }
  List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);    
  adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
  List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
  return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); // 根据配置信息生成一个Retrofit对象
}

Retrofit通过build模式来生成一个Retrofit对象

2. 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();
      @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)  throws Throwable {
        if (method.getDeclaringClass() == Object.class) {
          return method.invoke(this, args);
        }
        if (platform.isDefaultMethod(method)) {
          return platform.invokeDefaultMethod(method, service, proxy, args);
        }
        // 根据方法生成一个ServiceMethod对象(内部会将生成的ServiceMethod放入在缓存中,如果已经生成过则直接从缓存中获取)
        ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);  
       // 根据ServiceMethod对象和请求参数生成一个OkHttpCall对象,这个OkHttpCall能够调用OkHttp的接口发起网络请求
        OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); 
        // 调用serviceMethod的callAdapter的adapt方法,并传入okHttpCall,返回一个对象,这个的目的主要是为了适配返回类型,其内部会对OkhttpCall对象进行包装
        return serviceMethod.callAdapter.adapt(okHttpCall); 
    }
  });
}

Retrofit的create方法通过动态代理的模式,生成了实现了具体的网络请求接口的对象,并在InvocationHandler的invoke方法中统一处理网络请求接口实体对象的方法,invoke方法会通过方法构造一个ServiceMethod对象,并将其放入缓存中,然后根据ServiceMethod对象和网络请求的参数args去构造一个OkHttpCall对象,最后调用serviceMethod的callAdapter的adapt方法,传入将OkHttpCall对象,callAdapter的目的主要是为了适配OkHttpCall对象,其内部会对OkHttpCall对象进行包装,生成对应返回类型的对象

2. 动态代理

它的原理主要是在运行时动态生成代理类,然后根据代理类生成一个代理对象,在这个代理对象的方法中中又会调用InvocationHandler的invoke来转发对方法的处理

代理类的代码是动态生成的,生成代码后我们就可以用ClassLoader将其加载到内存中,并通过反射生成代理对象,代理类会将方法的处理转发给InvokeHandler,所以所有对代理对象方法的调用都会由InvocationHandler的invoke方法处理

2. ServiceMethod

ServiceMethod其实是用来存储一次网络请求的基本信息的,比如Host、URL、请求方法等,同时ServiceMethod还会存储用来适配OkHttpCall对象的CallAdpater

这篇先介绍到这里,下一篇主要分析动态代理、ServiceMethod以及出现的设计模式