Android框架源码解析之(五)Retrofit

源码地址: https://github.com/square/retrofit

Retrofit源码结构:
Android框架源码解析之(五)Retrofit_第1张图片
Android框架源码解析之(五)Retrofit_第2张图片

可以看出Retrofit是使用idea,maven依赖编写的Java工程,并不是一个Android 工程。

Retrofit的简单使用:
1、创建Service接口

public interface HistoryDataService {
    @GET("japi/toh?v=1.0&month=10&day=1&key=956c0df840307c89f68271325ccc8454")
    Call getResult();
}

2、创建 Call

        retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())//gson自动解析
                .baseUrl(NetworkConstant.JUHE_URL)//主机地址
                .build();
                
        HistoryDataService historyDataService = retrofit.create(HistoryDataService.class);
        Call call = historyDataService.getResult();

3、使用Call执行网络请求

        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                
            }

            @Override
            public void onFailure(Call call, Throwable t) {

            }
        });

Retrofit源码解析:
1、Retrofit 的创建过程
Retrofit是通过建造者模式构建出来的,看一些细节

//Retrofit.java
    public Builder() {
      this(Platform.get());
    }

看一下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) {
    }
    try {
      Class.forName("org.robovm.apple.foundation.NSObject");
      return new IOS();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }
  ......
  }

Platform 的get 方法最终调用了findPlatform方法,根据不同的平台获取不同的线程池。
看一下Android 的线程池:

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

    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      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将 Runnable 转发到UI线程
      }
    }
  }

其实就是个回调接口,使用Handler将 Runnable 转发到UI线程。

查看Build方法:

public Retrofit build() {
      if (baseUrl == null) { //baseurl不能为空,否则抛异常
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) { //如果没有手动设置callFactory,则直接new OkHttpClient, 用于后续网络请求
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) { //如果没有手动设置callbackExecutor,则获取平台默认的callbackExecutor,用于将Runable转发到UI线程,AndroidPlatform 默认使用Handler.post(Runable)
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      // 添加calladapter 用于后期子线程到主线程的回调
      List callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      // Make a defensive copy of the converters. //存储转化对象,例子中调用addConverterFactory(GsonConverterFactory.create()) ,设置返回的数据转化为Gosn可以解析的对象
      List converterFactories = new ArrayList<>( //converterFactories可以设置多个,retrofit会自动选择使用哪个converterFactoriy 解析数据
          1 + this.converterFactories.size() + platform.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());

      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
  }

2、Call 的创建过程

HistoryDataService historyDataService = retrofit.create(HistoryDataService.class);
  public  T create(final Class 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();
                                         //proxy 被代理的对象,method 被代理的方法,args方法参数
              @Override public Object invoke(Object proxy, Method method, 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);//如果是method是object的,则可以直接调用
                }
                if (platform.isDefaultMethod(method)) {//java8中接口引入默认方法,如果是接口的默认方法,直接调用
                  return platform.invokeDefaultMethod(method, service, proxy, args);
                }
                ServiceMethod serviceMethod = loadServiceMethod(method); //这个method是 HistoryDataService 的getResult()方法
                OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
                return serviceMethod.callAdapter.adapt(okHttpCall);  //这里创建ExeExecutorCallbackCall
              }
            });
  }

loadServiceMethod方法:

private final Map serviceMethodCache = new LinkedHashMap<>();

  ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {  //主要起一个缓存作用,如果存在method对应的ServiceMethod ,直接返回,如果不存在的话,创建并存入
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

查看 ServiceMethod.Builder(this, method).build();

  public ServiceMethod build() {
    callAdapter = createCallAdapter();//获取retrofit创建时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?");
    }
    responseConverter = createResponseConverter();//从retrofit创建时的responseConverter中,遍历,获取一个合适的Convert用来转换对象

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

ExecutorCallbackCall部分代码如下所示:

  static final class ExecutorCallbackCall implements Call {
    final Executor callbackExecutor;
    final Call delegate;

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

    @Override public void enqueue(final Callback callback) {
      if (callback == null) throw new NullPointerException("callback == null");

      delegate.enqueue(new Callback() {
        @Override public void onResponse(Call call, final Response 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 call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }

其实是将 call 封装为 ExecutorCallbackCall ,前面用到了适配器模式。
通过ExecutorCallbackCall 将请求结果回调到主线程。

3、Call 的 enqueue方法

 @Override public void enqueue(final Callback callback) {
    call.enqueue(new okhttp3.Callback() {//实际上调用的是okhttp3 Call 类型的call 的enqueue方法
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response response;
        try {
          response = parseResponse(rawResponse);//解析response
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }

 }

查看parseResponse 方法:

  Response parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    // Remove the body's source (the only stateful object) so we can pass the response along.
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    int code = rawResponse.code();//根据返回的不同状态码做不同的操作。
    if (code < 200 || code >= 300) {
      try {
        // Buffer the entire body to avoid future I/O.
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }

    if (code == 204 || code == 205) {
      return Response.success(null, rawResponse);
    }

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      T body = serviceMethod.toResponse(catchingBody);// 将 catchingBody 转为body
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
  }

看一下 serviceMethod的toResponse方法:

  /** Builds a method return value from an HTTP response body. */
  T toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);//这块将body转换为json,
  }

在之前的例子中,使用的是GsonConvertFactory ,查看一下GsonConvertFactory 的代码

  @Override
  public Converter responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter); //创建 GsonResponseBodyConverter
  }

查看GsonResponseBodyConverter 源码:

final class GsonResponseBodyConverter implements Converter {
  private final Gson gson;
  private final TypeAdapter adapter;

  GsonResponseBodyConverter(Gson gson, TypeAdapter adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }

  @Override public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      return adapter.read(jsonReader);
    } finally {
      value.close();
    }
  }
}

在 GsonResponseBodyConverter 的 convert 方法里将回调的数据转为Json格式,。

call的enqueue方法主要做的事是用Okhttp来请求网络,并将返回的Response进行数据转换回调给UI线程。

你可能感兴趣的:(Android框架源码解析)