Android网络编程(十二) 之 Retrofit2原理分析

1 使用回顾

我们在前面博文《Android网络编程(十一) 之 Retrofit2框架的使用》中已经对Retrofit的使用进行过介绍。今天我们接着往下来阅读Retrofit的关键源码从而它进行更加深入的理解。开始前,先来回顾一下简单的使用,通过使用步骤来深入分析每行代码背后的原理,代码如:

    // 0 创建一个网络请求的接口
    public interface AppInfoService {
        @GET("url.json")
        Call<List<AppInfo>> getAppInfoList(@Query("id") int id);
    }

    private void getRequest() {
        // 1 创建 Retrofit 对象,输入请求URL、转换器等
        Retrofit retorfit = new Retrofit.Builder()
                .baseUrl("https://api.xx.com/ ")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        // 2 通过Retrofit的create创建自定义的请求接口对象
        AppInfoService appInfoService = retorfit.create(AppInfoService.class);
        // 3 通过调用请求接口方法创建Call对象
        Call<List<AppInfo>> call = appInfoService.getAppInfoList(123);
        // 4 发起同步或异步的网络请求
//        try {
//            Response<List<AppInfo>> response = call.execute();
//            List<AppInfo> appInfos = response.body();
//            Log.e("zyx", appInfos.toString());
//
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
        call.enqueue(new Callback<List<AppInfo>>() {
            @Override
            public void onResponse(Call<List<AppInfo>> call, Response<List<AppInfo>> response) {
                List<AppInfo> appInfos = response.body();
                Log.e("zyx", appInfos.toString());
            }

            @Override
            public void onFailure(Call<List<AppInfo>> call, Throwable t) {
                Log.e("zyx", t.toString());
            }
        });
    }

可见其步骤大概是:

0 创建一个自定义的网络请求的接口,里头包含请求方式、请求服务端接口名和请求参数的传入的方法;

1 创建 Retrofit 对象,输入请求URL、转换器等;

2 通过Retrofit的create创建自定义的请求接口对象;

3 通过调用请求接口方法创建Call对象;

4 发起同步或异步的网络请求。

2 原理分析

2.1 创建Retrofit对象

Retrofit对象的创建过程也是使用了构造器模式进行的初始化。首先,Builder方法最终会调用到Platform类的findPlatform方法。

Retrofit.java

public static final class Builder {
  // ……
  Builder(Platform platform) {
    this.platform = platform;
  }

  public Builder() {
    this(Platform.get());
  }
}

Platform.java

class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }
}

上述代码可见,findPlatform方法内部会根据不同的运行平台来创建不同的Platform对象。接着调用其build方法。

Retrofit.java

public final class Retrofit {
public static final class Builder {
    private final Platform platform;
    private @Nullable okhttp3.Call.Factory callFactory;
    private @Nullable HttpUrl baseUrl;
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;

    // ……

    public Retrofit build() {
// 关键代码1,判断baseUrl是否为空
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      // 关键代码2,获得或创建 网络请求执行器工厂 okhttp3.Call.Factory对象
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      // 关键代码3,获得或创建回调方法执行器Executor对象
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

// 关键代码4,创建 网络请求适配器工厂CallAdapter.Factory列表,
// 并将callAdapterFactories和上面的callbackExecutor对象创建出默认的defaultCallAdapterFactories添加其中
      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

// 关键代码5,创建 数据转换器工厂Converter.Factory列表
      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(1 + this.converterFactories.size() + latform.defaultConverterFactoriesSize());
      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());
      // 关键代码6,实例化Retrofit对象
      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
  }
}

Build方法里逻辑很清晰,主要就是5件事情:

  1. 判断baseurl是否为空,baseurl的值就是通过. baseUrl方法进行设置。
  2. 获得网络请求执行器工厂callFactory对象值,若为空,则创建一个OkHttpClient对象,所以很明显Retrofit默认使用OkHttp进行网络请求,callFactory的值可通过. client方法进行设置。
  3. 获得回调方法执行器callbackExecutor对象值,若为空,则创建一个默认的,该默认的是一个MainThreadExecutor对象且它内部有一个带有Looper的Handler,我们后面再来讨论它。callbackExecutor的值可通过. callbackExecutor方法进行设置。
  4. 获得网络请求适配器工厂callAdapterFactories的值,将其添加到列表中,callAdapterFactories的值可通过. addCallAdapterFactory方法进行设置。列表创建完后再将关键代码3中的callbackExecutor对象添加其中。
  5. 创建一个数据转换器工厂Converter.Factory列表,之后添加内置的数据转换器BuiltInConverters和默认的数据转换器工厂defaultConverterFactories,其中还获得converterFactories的值,也将其添加到列表中,converterFactories的值可通过. addConverterFactory方法进行添加。
  6. 最后将上述对象传入Retrofit的构造函数中去实例化Retrofit对象,注意validateEagerly值表示提前验证,可通过. validateEagerly方法进行设置。

2.2通过Retrofit的create创建自定义的请求接口对象

如示例中代码 AppInfoService appInfoService = retorfit.create(AppInfoService.class);,Retrofit的create方法是一个泛型的方法,参数就是自定义的接口类型,返回值是一个Proxy.newProxyInstance动态代理对象,请看代码。

Retrofit.java

public final class Retrofit {
  // ……
  @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
  public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
// 关键代码1,是否提前验证
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
// 关键代码2,创建一个用于网络请求接口的动态代理对象并返回 
    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);
            }
// 关键代码3,加载网络请求接口里的方法,并执行
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }
private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
        loadServiceMethod(method);
      }
    }
  }
  // ……
}
  1. create方法内首先会判断validateEagerly变量是否为true,即是否提前验证,eagerlyValidateMethods方法其实也就是提前去触发关键代码3中loadServiceMethod方法逻辑。
  2. 关键代码2处,此处是创建了一个用于网络请求接口的动态代理对象,也就是当我们去调用使用回调示例中的AppInfoService的getAppInfoList方法时,最终会调用InvocationHandler的invoke方法。
  3. 关键代码3处,是加载网络请求的接口里的方法并执行,method就是我们自定义的getAppInfoList方法。

2.3通过调用请求接口方法创建Call对象

如示例中代码Call<List<AppInfo>> call = appInfoService.getAppInfoList(123);,该方法返回一个Call对象,从2.2中得知该方法最终会调用到Retrofit的loadServiceMethod方法返回对象的invoke方法中去,所以我们继续来看loadServiceMethod方法和invoke方法的代码。

2.3.1 loadServiceMethod方法

Retrofit.java

public final class Retrofit {
  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;
  }
// ……
}

loadServiceMethod方法内先从静态Map对象serviceMethodCache中读取是否存在之前创建过的网络请求实例,如果有就直接返回。否则通过ServiceMethod.parseAnnotations方法创建再添加到serviceMethodCache中去最后返回新创建对象。

ServiceMethod.java

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 关键代码1,创建一个请求工厂RequestFactory对象
    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.");
    }

// 关键代码2,创建HttpServiceMethod对象并返回
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

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

方法就是做了两件事情:

  1. 通过RequestFactory类的parseAnnotations方法创建一个请求工厂。
  2. 最终创建一个HttpServiceMethod对象并返回。

下面我们继续来分析RequestFactory的parseAnnotations方法和HttpServiceMethod的parseAnnotations方法逻辑。

2.3.1.1RequestFactory的parseAnnotations方法

RequestFactory.java

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

  private final Method method;
  private final HttpUrl baseUrl;
  final String httpMethod;
  private final @Nullable String relativeUrl;
  private final @Nullable Headers headers;
  private final @Nullable MediaType contentType;
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
  private final ParameterHandler<?>[] parameterHandlers;
  final boolean isKotlinSuspendFunction;

  RequestFactory(Builder builder) {
    method = builder.method;
    baseUrl = builder.retrofit.baseUrl;
    httpMethod = builder.httpMethod;
    relativeUrl = builder.relativeUrl;
    headers = builder.headers;
    contentType = builder.contentType;
    hasBody = builder.hasBody;
    isFormEncoded = builder.isFormEncoded;
    isMultipart = builder.isMultipart;
    parameterHandlers = builder.parameterHandlers;
    isKotlinSuspendFunction = builder.isKotlinSuspendFunction;
  }
// ……
  static final class Builder {
    // ……
    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() {
      // ……
      return new RequestFactory(this);
    }
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);
    } 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(method, "@Headers annotation is empty.");
      }
      headers = parseHeaders(headersToParse);
    } else if (annotation instanceof Multipart) {
      if (isFormEncoded) {
        throw methodError(method, "Only one encoding annotation is allowed.");
      }
      isMultipart = true;
    } else if (annotation instanceof FormUrlEncoded) {
      if (isMultipart) {
        throw methodError(method, "Only one encoding annotation is allowed.");
      }
      isFormEncoded = true;
    }
  }
// ……
}

可见RequestFactory的parseAnnotations方法其实就是传入Retrofit对象和method参数,然后通过读取method中定义的注解值(类中的parseMethodAnnotation方法),得到各种网络请求参数的一个对象。

2.3.1.2 HttpServiceMethod的parseAnnotations方法

获得RequestFactory对象后,就是作为参数传到HttpServiceMethod的parseAnnotations方法去,再看代码。

HttpServiceMethod.java

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    // ……
// 关键代码1,从Retrofit对象中的 网络请求适配器工厂 获得 网络请求适配器callAdapter和其请求类型
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
    if (responseType == okhttp3.Response.class) {
      throw methodError(method, "'" + getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (responseType == Response.class) {
      throw methodError(method, "Response must include generic type (e.g., Response<String>)");
    }
    // TODO support Unit for Kotlin?
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }

// 关键代码2,从Retrofit对象中的 数据转换器工厂 获得 数据转换器 responseConverter
    Converter<ResponseBody, ResponseT> responseConverter =  createResponseConverter(retrofit, method, responseType);

// 关键代码3,从Retrofit对象中的 获得 网络请求执行器工厂 callFactory
    okhttp3.Call.Factory callFactory = retrofit.callFactory;

// 关键代码4,根据类型创建不同的HttpServiceMethod实现
    if (!isKotlinSuspendFunction) {
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
          callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
    } else {
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
          callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
          continuationBodyNullable);
    }
  }
  // ……
}

HttpServiceMethod的parseAnnotations方法里会去获取之前在Retrofit对象中的 网络请求适配器callAdapter、数据转换器responseConverter、网络请求执行器工厂callFactory 以及 通过参数传入的请求工厂RequestFactory作为参数,去根据不同类型创建三种分别是CallAdapted,SuspendForResponse和SuspendForBody的HttpServiceMethod对象。其中SuspendForResponse和SuspendForBody是Kotlin suspend 方法的支持,所以我们只看CallAdapted便可以了。

HttpServiceMethod.java

static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
  private final CallAdapter<ResponseT, ReturnT> callAdapter;

  CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
      Converter<ResponseBody, ResponseT> responseConverter,
      CallAdapter<ResponseT, ReturnT> callAdapter) {
    super(requestFactory, callFactory, responseConverter);
    this.callAdapter = callAdapter;
  }

  @Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
    return callAdapter.adapt(call);
  }
}

 2.3.2 invoke方法

看回上面的 return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); 代码,当loadServiceMethod方法返回了ServiceMethod对象后,接着就是调用它的invoke方法。

ServiceMethod.java

abstract class ServiceMethod<T> {
  // ……
  abstract @Nullable T invoke(Object[] args);
}

invoke方法的实现在HttpServiceMethod类中。

HttpServiceMethod.java

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
// ……
@Override final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }
  protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
}

Invoke方法很简单,就是调用adapt方法,也就是HttpServiceMethod的实现类CallAdapted中的adapt方法。其代码已经在上面贴过。这里请记住第一个参数call是OkHttpCall。

HttpServiceMethod.java

static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
  //……
  @Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
    return callAdapter.adapt(call);
  }
}

最终就是 网络请求适配器callAdapter的adapt方法。

这个网络请求适配器callAdapter就是在HttpServiceMethod的parseAnnotations方法中关键代码1中,从Retrofit对象中的 网络请求适配器工厂 获得的 网络请求适配器callAdapter。回顾一下上面创建Retrofit对象中的 网络请求适配器工厂,当时提到该 网络请求适配器工厂callAdapterFactories的值可通过. addCallAdapterFactory方法进行设置 和 默认的defaultCallAdapterFactories

Platform.java

List<? extends CallAdapter.Factory> defaultCallAdapterFactories(@Nullable Executor callbackExecutor) {
  return singletonList(new DefaultCallAdapterFactory(callbackExecutor));
}
DefaultCallAdapterFactory.java
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  private final @Nullable Executor callbackExecutor;

  DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  @Override public @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    if (!(returnType instanceof ParameterizedType)) {
      throw new IllegalArgumentException("Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
    }
    final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
    final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ? null : callbackExecutor;

    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
      }
    };
  }
}

最终,如果我们没有通过. addCallAdapterFactory方法指定callAdapter的话,invoke方法会执行到DefaultCallAdapterFactory类中,所以创建Call对象就是ExecutorCallbackCall对象。

DefaultCallAdapterFactory的ExecutorCallbackCall构造方法接收两个参数。先说说第二个参数call,我们在HttpServiceMethod的invoke中可知是一个OkHttpCall对象。而第一个参数executor是在创建Retrofit对象时的回调方法执行器callbackExecutor,如果当时不通过.callbackExecutor方法设置的话,它默认是platform.defaultCallbackExecutor();,一个MainThreadExecutor对象,它的源码如下,可见它内部有一个带有Looper的Handler。

Platform.java

class Platform {
  // ……
  static class Android extends Platform {
    // ……
    @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);
      }
    }
  }
}

2.4发起网络请求

获得Call对象后就是最后发请网络请求。从上面我们得知Call对象就是DefaultCallAdapterFactory.ExecutorCallbackCall,所以无论是异步还是同步的请求,都是调用了DefaultCallAdapterFactory.ExecutorCallbackCall里的enqueue和execute方法。源码如下。

DefaultCallAdapterFactory.java

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  // ……
  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.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);
            }
          });
        }
      });
    }

@Override public Response<T> execute() throws IOException {
      return delegate.execute();
    }
// ……
}

enqueue和execute方法内都是代理了delegate对象执行,而delegate对象就是OkHttpCall对象。所以我们只看OkHttpCall的enqueue逻辑就会明白了。

OkHttpCall.java

final class OkHttpCall<T> implements Call<T> {
  // ……
  @Override public void enqueue(final Callback<T> callback) {
    // ……
    okhttp3.Call call;
    // ……
      if (call == null && failure == null) {
        try {
// 关键代码1,创建okhttp3的call对象
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          // ……
        }
      }
    }
    // ……
// 关键代码2,执行call对象的异常请求
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response<T> response;
        try {
// 关键代码3,获得请求结果进行解析
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          throwIfFatal(e);
          callFailure(e);
          return;
        }

        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        callFailure(e);
      }
      // ……
    });
  }
  private okhttp3.Call createRawCall() throws IOException {
    okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }
}

关键代码1中通过createRawCall方法创建了一个okhttp3的call对象,接着在关键代码2中去执行okhttp3的异常请求,然后在关键代码3中通过parseResponse方法进行了请求结果的解析和封装。最后结果再回调到ExecutorCallbackCall中去,而我们知道okhttp3的回调是执行在子线程中的,在ExecutorCallbackCall也就是MainThreadExecutor对象,因为它本身带有Looper的Handler,所以最终将结果回调到主线程中去执行。

同理,同步的方法execute也是调用了okhttp3的call对象的execute方法,最终也是通过parseResponse方法进行了请求结果的解析和封装。

3 总结

至此,关于Retrofit2框架就介绍完毕,虽然过程中省略了大量的细节,但整体过程原理还是通过源码了解很多。那我们现在用简短的话来总结一下原理:

1创建Retrofit对象,内部先会根据不同的运行平台来创建不同的Platform对象。然后通过构造器模式进行参数的初始化,如使用:

  1. 使用baseUrl方法设置要访问的URL;
  2. 选择性使用callFactory方法创建“网络请求执行器工厂”callFactory,若不使用该方法,则会创建一个OkHttpClient对象;
  3. 选择性使用callbackExecutor方法创建“回调方法执行器”callbackExecutor,若不使用该方法,则创建一个默认的defaultCallbackExecutor,它是一个带Looper的Handler的MainThreadExecutor对象;
  4. 选择性使用addCallAdapterFactory方法添加“网络请求适配器工厂”,以及追加一个默认的网络请求器DefaultCallAdapterFactory;
  5. 选择性使用addConverterFactory方法添加“数据转换器工厂”中;
  6. 最后通过上述创建的对象进行实例化Retrofit。

2通过Retrofit的泛型方法create并会传入自定义的接口类型来创建自定义的请求接口对象,该对象是使用了Proxy.newProxyInstance的动态代理对象。

3通过调用自定义的请求接口方法创建Call对象,

  1. 内部先获取定义方法中的注解值创建一个“请求工厂”RequestFactory,然后再获取前面Retrofit对象中的“网络请求适配器”callAdapter、“数据转换器”responseConverter、“网络请求执行器工厂”callFactory 以及 刚创建的“请求工厂”RequestFactory,根据类型创建出继承于HttpServiceMethod的CallAdapted对象;
  2. 因为使用了动态代理,所以最后会调用到CallAdapted对象的adapt方法去,又因为默认的“网络请求适配器”就是DefaultCallAdapterFactory对象,所以最后adapt方法内部创建的Call对象就是ExecutorCallbackCall对象。

4发起网络请求,就是通过DefaultCallAdapterFactory.ExecutorCallbackCall的enqueue和execute方法来执行异步和同步。这两个方法都是通过一个OkHttpCall对象来完成,OkHttpCall内部就是封装了okhttp3的网络请求。待请求完成后更是将结果回调回到ExecutorCallbackCall里,再通过带Looper的Handler的MainThreadExecutor回调方法执行器将结果回调到调用方的主线程中去。

 

 

 

发布了106 篇原创文章 · 获赞 37 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/lyz_zyx/article/details/103728964