Retrofit 网络框架源码解析(一)

18 篇文章 0 订阅

一、Okhttp请求

示例代码:

private void testOkHttp() {
        // step1
        OkHttpClient client = new OkHttpClient();
        // step2
        Request request = new Request.Builder()
                .url("https://www.google.com.hk")
                .build();
        // step3
        Call call = client.newCall(request);
        // step4 发送网络请求,获取数据,进行后续处理
        call.enqueue(new okhttp3.Callback() {
            @Override
            public void onFailure(okhttp3.Call call, IOException e) {

            }

            @Override
            public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {

            }
        });
    }

上面示例代码解析:
step1:创建 HttpClient 对象,也就是构建一个网络类型的实例,一般会将所有的网络请求使用同一个单例对象。
step2:构建 Request,也就是构建一个具体的网络请求对象,具体的请求 url,请求头,请求体等等。
step3:构建请求 Call,也就是将具体的网络请求与执行请求的实体进行绑定,形成一个具体的正式的可执行体。
step4:后面就是进行网络请求了,然后处理网络请求的数据。

总结一下:
OkHttp 的意义:OkHttp 是基于 Http 协议封装的一套请求客户端,虽然它可以开线程,但根本上它更偏向真正的请求,跟 HttpClient,HttpUrlConnection 的职责是一样的。
OkHttp 的职责:OkHttp 主要负责 socket 部分的优化,比如多路复用,buffer 缓存,数据压缩等等。
OkHttp 给用户留下的问题:
1)用户网络请求的接口配置繁琐,尤其是需要配置请求 body,请求头,参数的时候;
2)数据解析过程需要用户手动拿到 responsebody 进行解析,不能复用;
3)无法适配自动进行线程的切换;
4)万一存在网络嵌套网络请求就会陷入“回调陷阱”

二、Retrofit 请求

示例代码使用:
导入相关包:

// Retrofit的依赖
implementation 'com.squareup.retrofit2:retrofit:2.1.0'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'

代码示例

// step1  建立一个Retrofit对象,配置好Retrofit类的成员变量
Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.wanandroid.com")  //网络请求的url地址
                .addConverterFactory(GsonConverterFactory.create(new Gson()))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
// step2 创建一个ISharedListService接口类的对象,create函数内部使用了动态代理来创建接口
//对象,这样的设计可以让所有的访问请求都被代理
ISharedListService sharedListService = retrofit.create(ISharedListService.class);

// step3 调用getSharedList的时候,在动态代理里面,会存在一个函数 getSharedList,
// 这个函数里面会调用 invoke,这个 invoke 函数也就是retrofit 里面的 invoke 函数
// 目的:将接口转换成网络请求
Call<SharedListBean> sharedListCall = sharedListService.getSharedList(2, 1);  //这里返回的是ExecutorCallbackCall对象

// step4
sharedListCall.enqueue(new Callback<SharedListBean>(){
	@Override
	public void onResponse(Call<SharedListBean> call, Response<SharedListBean> response) {
		if (response.isSuccessful()) {
			System.out.println(response.body().toString());
		}
	}
	
	@Override
	public void onFailure(Call<SharedListBean> call, Throwable t) {
		t.printStackTrace();
	}
})

上面示例代码解析:
step1: 创建 retrofit 对象,构建一个网络请求的载体对象,和 OkHttp 构建 OKHttpClient 对象有一样的意义,只不过 retrofit 在 build 的时候有非常多的初始化内容,这些内容可以为后面网络请求提供准备,如准备 线程转换Executor, Gson convert,RxjavaCallAdapter。
step2:Retrofit 的精髓,为统一配置网络请求完成动态代理的设置。
step3:构建具体网络请求对象 Request(service), 在这个阶段要完成的任务:
1)将接口中的注解翻译成对应的参数;
2)确定网络请求参数的返回值 response 类型以及对应的转换器;
3)将 OkHttp 的 Request 封装成为 Retrofit 的 OkhttpCall。
总的来说,就是根据请求 service 的 interface 来封装 Okhttp 请求 Request。
step4: 后面就进行网络请求,然后处理网络请求的数据。

其中:
baseUrl:网络请求的url地址
callFactory:网络请求工厂
callbackExecutor:回调方法执行器
adapterFactories:网络请求适配器工厂的集合
coverterFatories:数据转换器工厂的集合

总结一下:
Retrofit 主要负责应用层面的封装,就是说主要面向开发者,方便使用,比如请求参数,响应数据的处理,错误处理等等。
Retrofit 封装了具体的请求,线程切换以及数据转换。
网上一般都推荐 RxJava + Retrofit + OkHttp 框架,Retrofit 负责请求的数据和请求的结果,使用接口的方式呈现,OkHttp 负责请求的过程,Rxjava 负责异步,各种线程之间的切换,用起来非常便利。

ISharedListService.java

public interface ISharedListService {

    @GET("user/{userid}/share_articles/{pageid}/json")
    Call<SharedListBean> getSharedList(@Path("userid") int it, @Path("pageid") int pageid);

}

retrofit是如何封装请求的

在这里插入图片描述
  大体的网络流程是一致的,毕竟都是通过okhttp进行网络请求。主要的步骤都是:创建网络请求实体client -> 构建真正的网络请求 -> 将网络请求方案与真正的网络请求实体结合构成一个请求Call -> 执行网络请求 -> 处理返回数据 -> 处理 Android 平台的线程问题。
  在上图中,我们看到的对比最大的区别是:
1)okhttp创建的是OkHttpClient,然而retrofit创建的是Retrofit实例
2)构建Request的流程,retrofit是通过注解来进行适配
3)配置Call的过程中,retrofit是利用Adapter适配的OkHttp的Call
4)相对okhttp,retrofit会对responseBody进行自动的Gson解析
5)相对okhttp,retrofit会自动的完成线程的切换

三、Retrofit的构建过程

  Retrofit 通过build模式来生成一个Retrofit对象,通过代码我们知道,Retrofit默认会使用Okhttp来发送网络请求,当然,我们也可以自己定制。
  执行step1中的build()操作,进入下面的build流程

Retrofit.java

  public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
    
     // 代码1
     // 默认只支持 okhttp 请求,不支持 httpurlconnection 和 httpclient
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

     // 代码2
     // 添加一个线程管理 Executor, okhttp 切换线程需要手动处理,但是 retrofit
     //不需要,就是因为这个 Executor 的存在,其实它是handler
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // 代码3
      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); // 添加一个默认的callAdapterFatory
      
      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }
其中,build流程采用构建/建造者设计模式和外观/门面设计模式。

1: 在代码1处
  初始化构建call的工厂,但是这个地方直接就是使用了okhttp的call,没有使用到工厂设计模式去添加构建httpclient 或者 httpurlconnection的方法来创建call,说明retrofit已经铁下心只支持okhttp创建call请求。
  此次调用,目的就是创建一个OkHttpClient,换句话说,这里的调用就是生产Okhttp网络请求需要的请求Call,以备后面进行真正的网络请求。

2:在代码2处
  网络请求需要在子线程中执行,那么就需要线程管理,所有就有了代码2的存在,深入源码后发现,这个地方就是运用handler进行线程切换,当网络请求回来了进行线程切换,可以看下面的源码:
Platform.java

static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

  所以,此次调用,目的是构建一个用handler封装的Executor,以备后面进行网络请求成功后的线程切换用。

3:在代码3处
设置默认CallAdapterFactory
  在此添加的CallAdapterFactory属于系统默认的,当然,我们可以添加RxJavaCallAdapterFactory。默认的CallAdapterFactory是ExecutorCallAdapter类的对象,在Platform.java Class里面可以梳理出来
Platform.java

  CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    if (callbackExecutor != null) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    return DefaultCallAdapterFactory.INSTANCE;
  }

  所以构建的Retrofit都是用于进行后面请求的需要的内容的一个准备工作。也就是封装OkHttp需要的准备工作。

最后new 了一个Retrofit对象
Retrofit.java

public final class Retrofit {
  // 网络请求配置对象(对网络请求接口中方法注解进行解析后得到的对象)
  // 作用:存储网络请求相关的配置,如网络请求的方法、数据转换器、网络请求适配器
  private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();

  // 网络请求器的工厂
  // 作用:生产网络请求器(Call)
  // Retrofit 是默认使用okhttp
  final okhttp3.Call.Factory callFactory;
  
  // 网络请求的url地址
  final HttpUrl baseUrl;
  
  // 数据转换器工厂的集合
  // 作用:放置数据转换器工厂
  // 数据转换器工厂作用:生产数据转换器(converter)
  final List<Converter.Factory> converterFactories;

  // 网络请求适配器工厂的集合
  // 作用:放置网络请求适配器工厂
  // 网络请求适配器工厂作用:生产网络请求适配器(CallAdapter)
  final List<CallAdapter.Factory> adapterFactories;
 
  // 回调方法执行器
  final @Nullable Executor callbackExecutor;

  // 标志位
  // 作用:是否提前对业务接口中的注解进行验证转换的标志位
  final boolean validateEagerly;

  Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
      @Nullable 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;
  }
  ... 
}

四、Retrofit构建IxxxService对象的过程(Retrofit.create())

看下面的代码:

ISharedListService sharedListService = retrofit.create(ISharedListService.class);
Call<SharedListBean> sharedListCall = sharedListService.getSharedList(2, 1);

  上面两行代码需要连起来才能正确的被阅读,因为,在create里面是使用了动态代理的技术方案,而动态代理是运行时生效的
  执行step2,调用Retrofit的create()方法,create函数内部使用了动态代理来创建接口对象,这样的设计可以让所有的访问请求都被代理

create()方法里面采用动态代理设计模式,这个里面采用AOP切面编程思想

Retrofit.java

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 the method is a method from Object then defer to normal invocation.
            // 说明方法的过滤,会过滤掉默认的不需要管理的方法
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            // 默认情况下,java的接口是不能够有默认实现的,但是Java8 可以默认实现
            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 的 adapter方法,并传入 okhttpCall,返回一个对象,
            // 这个的目的主要是为了适配返回类型,其内部会对OkHttpCall对象进行包装
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

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

4.1 动态代理

  动态代理的原理主要是在运行时动态生成代理类,然后根据代理类生成一个代理对象,在这个代理对象的方法中又会调用InvocationHandler的invoke来转发对方法的处理。
  在使用retrofit的时候,对每一个网络请求的产生都必须要先调用create函数,也就意味着,我们的请求都是通过代理类来进行处理的。但是代理类具体的代理行为是发生在哪里呢?很明显,它并不是在create函数执行的时候,而是在使用具体的接口创建具体网络请求Call的时候,当调用具体网络请求Call的代码示例如下:

Call<SharedListBean> sharedListCall = sharedListService.getSharedList(2, 1);

  在执行上面 代码的时候,它会走代码设计模式的InvocationHandler里面的invoke()函数,也就是所有的网络请求在创建具体网络请求Call的时候,都会走invoke, 从而我们可以在invoke里面进行各种行为的统一处理,比如:接口的统一处理,也就是注解的解读和网络请求参数的拼接。

  在代码执行create()方法时,执行到Proxy.newProxInstance()时,在运行时会动态创建一个代理类对象类如ISharedListServiceProxy,并且该类实现了ISharedListService接口

代理类:

class ISharedListServiceProxy implement ISharedListService{

	 // toString();
	 // hashCode();  等等一系列方法
	 ... 
	 // 接口方法
	 public void getSharedList(int it, int pageid) {
		 invocationHandler.invoke(it, pageid);
	 }

}

4.2 ServiceMethod

  执行动态代理的invoke()方法,会执行 loadServiceMethod()方法
其实就将注解、参数都转化成网络请求Call的参数,一个请求对于一个ServiceMethod

Retrofit.java

ServiceMethod<?, ?> loadServiceMethod(Method method) {
    // 为什么会缓存--》为了效率
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build(); // 采用建造者设计模式
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

  loadServiceMethod首先会从缓存中获取ServiceMethod对象,如果没有,则通过Method和Retrofit对象构造一个ServiceMethod对象,并将其放入缓存中。
  每一个method都有一个自己的ServiceMethod,这就意味着ServiceMethod是属于函数的,而不是类的。也就是我们定义的网络访问接口类,在接口类里面的每一个函数都会在反射阶段形成自己的serviceMethod。
  ServiceMethod其实是用来存储一次网络请求的基本信息的,比如Host、URL、请求方法等,同时ServiceMethod还会存储用来适配OkHttpCall对象的CallAdapter。ServiceMethod的build方法会解读传入的Method,首先ServiceMethod会在CallAdapterFactory列表中寻找合适的CallAdapter来包装OkHttpCall对象的,这一步主要是根据Method的返回参数来匹配的,比如如果方法的返回参数是Call对象,那么ServiceMethod就会使用默认的CallAdapterFactory来生成CallAdapter,而如果返回对象是RxJava的Observable对象,则会使用RxJavaCallAdapterFactory提供的CallAdapter。如果build方法会解读Method的注解,来获得注解上配置的网络请求信息,比如请求方法、URL、Header等。

ServiceMethod.java

final class ServiceMethod<R, T> {
  // Upper and lower characters, digits, underscores, and hyphens, starting with a character.
  static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
  static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
  static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);

  // 网络请求工厂    也就是okhttp的网络请求 
  final okhttp3.Call.Factory callFactory;
  // 网络请求适配器   把call请求适配各个平台
  final CallAdapter<R, T> callAdapter;

  // 网络基地址
  private final HttpUrl baseUrl;
  // 数据转换器
  private final Converter<ResponseBody, R> responseConverter;
  // 网络请求的http方法    比如 get、post方法
  private final String httpMethod;
  // 网络请求的相对地址   和 baseUrl 拼接起来就是实际地址
  private final String relativeUrl;
  // 请求头
  private final Headers headers;
  // 网络请求的 http 报文的 type
  private final MediaType contentType;
  // 三个标志位
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
  // 方法参数的处理器   比如我们定义的方法   上面的 get 和后面的参数
  private final ParameterHandler<?>[] parameterHandlers;

  // 构建一系列的变量
  ServiceMethod(Builder<R, T> builder) {
    this.callFactory = builder.retrofit.callFactory();
    this.callAdapter = builder.callAdapter;
    this.baseUrl = builder.retrofit.baseUrl();
    this.responseConverter = builder.responseConverter;
    this.httpMethod = builder.httpMethod;
    this.relativeUrl = builder.relativeUrl;
    this.headers = builder.headers;
    this.contentType = builder.contentType;
    this.hasBody = builder.hasBody;
    this.isFormEncoded = builder.isFormEncoded;
    this.isMultipart = builder.isMultipart;
    this.parameterHandlers = builder.parameterHandlers;
  }

  static final class Builder<T, R> {
    final Retrofit retrofit;
    final Method method;
    final Annotation[] methodAnnotations;
    final Annotation[][] parameterAnnotationsArray;
    final Type[] parameterTypes;

    Type responseType;
    boolean gotField;
    boolean gotPart;
    boolean gotBody;
    boolean gotPath;
    boolean gotQuery;
    boolean gotUrl;
    String httpMethod;
    boolean hasBody;
    boolean isFormEncoded;
    boolean isMultipart;
    String relativeUrl;
    Headers headers;
    MediaType contentType;
    Set<String> relativeUrlParamNames;
    ParameterHandler<?>[] parameterHandlers;
    Converter<ResponseBody, T> responseConverter;
    CallAdapter<T, R> callAdapter;

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

    public ServiceMethod build() {
      callAdapter = createCallAdapter();  //查找能适配返回类型的CallAdapter
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      // 设置请求的数据适配器converter
      responseConverter = createResponseConverter();
      
	  // 解读方法的注解,methodAnnotations表示方法上的所有注解 
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      if (httpMethod == null) {
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }

      if (!hasBody) {
        if (isMultipart) {
          throw methodError(
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
          throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      if (relativeUrl == null && !gotUrl) {
        throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError("Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError("Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError("Multipart method must contain at least one @Part.");
      }

      return new ServiceMethod<>(this);  // new了一个ServiceMethod
    }

  ServiceMethod 作用就是解析注解、解析请求的返回值这一系列过程
  retrofit是对整个网络请求的一个保存,ServiceMethod是对某一个接口请求(具体的网络请求)的保存,就是从retrofit中所保存的一系列参数列表中找到对应的参数
在这里插入图片描述

4.3 okHttpCall

OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);

  我们知道,ServiceMethod封装了网络请求的基本信息,比如Host、URL等,我们根据ServiceMethod和请求参数args就可以确定本次网络请求的所有信息了,OkHttpCall主要是将这些信息封装起来,并调用OkHttp的接口去发送网络请求,这里,我们就将OkHttpCall看成是一个处理网络请求的类即可。

4.4 callAdapter

在retrofit中,invoke()里面的最后一行代码,

return serviceMethod.callAdapter.adapt(okHttpCall);

下面对这行代码的执行流程进行分析:
这条语句分两步进行分析:
第一步:首先先进行分析serviceMethod.callAdapter是在哪进行赋值的
ServiceMethod.java

public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      responseConverter = createResponseConverter();
	  ...
}

  在执行loadServiceMethod()的流程中,会执行到ServiceMethod类的build()方法,从而对执行了createCallAdapter()方法,并对callAdapter进行了赋值。
ServiceMethod.java

private CallAdapter<T, R> createCallAdapter() {
      Type returnType = method.getGenericReturnType();
      if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(
            "Method return type must not include a type variable or wildcard: %s", returnType);
      }
      if (returnType == void.class) {
        throw methodError("Service methods cannot return void.");
      }
      Annotation[] annotations = method.getAnnotations();
      try {
        //noinspection unchecked
        return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);  //执行该条语句
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }

执行retrofit.callAdapter()语句继续往下流程
Retrofit.java

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

执行nextCallAdapter()流程
Retrofit.java

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    int start = adapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      // 从Factory中去取对应的CallAdapter
      CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

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

  执行 CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this); 这条语句,返回对应的CallAdapter对象,其中adapterFactories是在执行step1流程的build()语句会对该List列表进行添加数据

List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories); 
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

  特别注意这个地方的callbackExecutor参数,其实是build()语句里面进行new出来的。
Retrofit.java

Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
    callbackExecutor = platform.defaultCallbackExecutor();
}

转而执行Android平台下的defaultCallbackExecutor()
Platform.java

@Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }
    ... 
static class MainThreadExecutor implements Executor {
  private final Handler handler = new Handler(Looper.getMainLooper());

  @Override public void execute(Runnable r) {
    handler.post(r);
  }
}

其实最后就是调用创建了一个Handler在主线程中执行后续的流程。

  在回到adapterFactories.add()操作,默认添加的数据是platform.defaultCallAdapterFactory(callbackExecutor),从而执行到Android平台的defaultCallAdapterFactory()方法。

Platform.java

@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

  最后new了一个ExecutorCallAdapterFactory对象,也就是说adapterFactories.get(i)获取的就是一个ExecutorCallAdapterFactory对象,执行adapterFactories.get(i).get(returnType, annotations, this)就是执行到了ExecutorCallAdapterFactory的get()方法。
ExecutorCallAdapterFactory.java

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    // 返回一个CallAdapter
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

第二步:再回到下面这条语句return serviceMethod.callAdapter.adapt(okHttpCall);,执行adapte流程也就是执行了ExecutorCallAdapterFactory里面get()方法里面的adapt()方法,

@Override public Call<Object> adapt(Call<Object> call) {
	// 将okhttpCall转换为ExecutorCallbackCall,这个地方采用适配器设计模式
    return new ExecutorCallbackCall<>(callbackExecutor, call); 
}

  最后就是新建了一个ExecutorCallbackCall对象。
  也就是说serviceMethod.callAdapter.adapt()返回给执行这条语句
Call<SharedListBean> sharedListCall = sharedListService.getSharedList(2, 1); 返回的是ExecutorCallbackCall对象(ExecutorCallbackCall 实现Call接口)


  那么我们可以设想一下为什么Retrofit还要设计一个CallAdapter接口呢?
先来说一个客观事实,Retrofit真正使用okhttp进行网络请求的就是OkHttpCall这个类

  曾提到了Call对象的创建是通过ServiceMethod.adapter()完成的,这里在看看该方法的源码:
ServiceMethod.adapter()方法:

T adapte(Call<R> call) {
	return callAdapter.adapte(call);
}

  通过上述源码可知,最终Call对象是调用CallAdapter.adapter(Call)方法创建的,那么CallAdapter及具体的Call对象又是如何生成的呢?
如果没有这个适配器模式,会出现上面情况?
  很明显,没有适配器的时候此时我们网络请求的返回接口只能直接返回OkHttpCall,那么所有的网络请求都是用okhttpCall进行,这样的话就失去了retrofit封装网络请求call的意义了,譬如:RxjavaCallAdapterFactory就没有办法支持。
  如果我们想要返回的不是Call呢?比如Rxjava的Observable,这种情况下该怎么办呢?
适配器模式在此发挥了其应用的作用
  将网络请求的核心类OkHttpCall进行适配,你需要什么类型的数据就通过适配器适配,返回适配后的对象就是了,正是这种CallAdapter接口的设计,使得我们在使用Retrofit的时候可以自定义我们想要的返回类型。此接口的设计也为Rxjava的扩展使用做了很好的基础。

五、Retrofit网络请求操作

  执行step4步骤的sharedListCall.enqueue()步骤,也就是执行了ExecutorCallbackCall的enqueue()方法
ExecutorCallAdapterFactory.java

static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;
    final Call<T> delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }

    @Override public void enqueue(final Callback<T> callback) {
      checkNotNull(callback, "callback == null");
      // delegate就是okHttpCall对象
      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          // 这条语句在主线程中执行
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

        @Override public void onFailure(Call<T> call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }

  其中,delegate变量是从执行这条语句return serviceMethod.callAdapter.adapt(okHttpCall);传递过来的参数okHttpCall,delegate.enqueue()就相当于执行OkHttpCall对象的enqueue()方法。
OkHttpCall.java

@Override public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          // 代码1
          // 创建一个真正的call对象
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }
    // 代码2
   //执行okhttp3 Call的enqueue,也就是okhttp的enqueue流程
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callSuccess(Response<T> response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

1:在代码1处
执行createRawCall()方法
OkHttpCall.java

  private okhttp3.Call createRawCall() throws IOException {
    // 通过serviceMethod保存的参数去构建一个okhttp的request
    Request request = serviceMethod.toRequest(args);
    // 构建一个okhttp的call
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

  通过调用serviceMethod.toRequest()方法将serviceMethod中保存的参数去构建一个okhttp的request请求
ServiceMethod.java

 Request toRequest(@Nullable Object... args) throws IOException {
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart);

    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

    int argumentCount = args != null ? args.length : 0;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException("Argument count (" + argumentCount
          + ") doesn't match expected count (" + handlers.length + ")");
    }

    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }

    return requestBuilder.build();
  }

RequestBuilder.java

  Request build() {
    HttpUrl url;
    HttpUrl.Builder urlBuilder = this.urlBuilder;
    if (urlBuilder != null) {
      url = urlBuilder.build();
    } else {
      // No query parameters triggered builder creation, just combine the relative URL and base URL.
      //noinspection ConstantConditions Non-null if urlBuilder is null.
      url = baseUrl.resolve(relativeUrl);
      if (url == null) {
        throw new IllegalArgumentException(
            "Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl);
      }
    }

    RequestBody body = this.body;
    if (body == null) {
      // Try to pull from one of the builders.
      if (formBuilder != null) {
        body = formBuilder.build();
      } else if (multipartBuilder != null) {
        body = multipartBuilder.build();
      } else if (hasBody) {
        // Body is absent, make an empty body.
        body = RequestBody.create(null, new byte[0]);
      }
    }

    MediaType contentType = this.contentType;
    if (contentType != null) {
      if (body != null) {
        body = new ContentTypeOverridingRequestBody(body, contentType);
      } else {
        requestBuilder.addHeader("Content-Type", contentType.toString());
      }
    }

    return requestBuilder
        .url(url)
        .method(method, body)
        .build();
  }

2:在代码2处
  执行call.enqueue(),call是 okhttp3.Call对象,也就是最后执行到okhttp的enqueue流程。

1.OkHttpCall 对 OkHttp3 Call进行了封装,ExecutorCallbackCall对OkHttpCall进行了封装,ExecutorCallbackCall功能增强的地方是调用callbackExecutor.execute()进入主线程中执行callback。这个地方采用了装饰器设计模式
2.在执行new ExecutorCallbackCall<>(callbackExecutor, call)的过程,就是将okhttpCall转换成ExecutorCallbackCall的过程,这个地方采用了适配器设计模式
3. 如果这条语句Call<SharedListBean> getSharedList(@Path("userid") int it, @Path("pageid") int pageid),需要方法的返回类型为Rxjava的Observable对象而不是Call<SharedListBean>,这个过程也采用适配器设计模式
4. 在进行Rxjava进行转换的时候,包含ResponseCallAdapter、SimpleCallAdapter、ResultCallAdapter,根据返回结果的不同使用不同的适配器,选择不同适配器算法的过程是采用策略设计模式


  一般的Retrofit网络请求的操作是指Call.execute() & Call.enqueue()的过程,这个过程才是真正的网络请求,因为,网络配置,请求地址配置,Call适配,网络请求requestBody & 返回值responseBody转化适配准备工作都已经完成。

sharedListCall.enqueue(new Callback()...);
sharedListCall.execute();

  在进行网络请求执行的时候,基本上就是调用,ServiceMethod中设置的各个内容如:
1)OkHttpCall进行网络请求,实则是进行okhttp的网络请求;
2)利用converter进行网络请求数据的转换,一般是Gson();
3)利用rxjava observable构建rxjava类型的责任链访问方案,并进行线程切换;
4)如果没有rxjava的添加,那么就使用默认的callAdapter里面的callbackExecutor进行线程的切换,进行网络请求。

整体网络请求的流程图:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值