Retrofit源码分析

准备工作

我们首先先定义并实现接口,然后通过断点调试一步一步地深入了解retrofit的源码。

//定义接口
public interface CyyHttpService {
    @GET("{token}/account/total/fetch")
    Call<ResponseBody<String>> getTotal(@Path("token") String token);
    @POST("auth")
    Call<UserDTO> userLogin(@Body JSONObject body);
}

//创建retrofit实例
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://.../")
        .addConverterFactory(GsonConverterFactory.create(myGson()))
        .build();

//接口实现
CyyHttpService service = retrofit.create(CyyHttpService.class);
Call<ResponseBody<String>> total = service.getTotal("token");

total.enqueue(new Callback<ResponseBody<String>>() {
            @Override
            public void onResponse(Call<ResponseBody<String>> call, 
                                   Response<ResponseBody<String>> response) {

            }

            @Override
            public void onFailure(Call<ResponseBody<String>> call, Throwable t) {

            }
        });

工作流程:

  1. 通过Retrofit.Builder()创建Retrofit实例。
  2. 调用Retrofit的create()方法将生成接口CyyHttpService的实例。
  3. 调用CyyHttpService的getTotal()方法获得 Call
  4. 执行 Call> 的enqueue方法在回调中处理返回的 ResponseBody

源码中包含的类

先了解一下其源码下有哪些类:

  • BuiltInConverters

    默认的转换器

  • Call

    这个接口主要的作用就是发送一个HTTP请求,Retrofit默认的实现是OkHttpCall,你可以根据实际情况实现你自己的Call

  • CallAdapter

    这个接口包含2个方法:

    Type responseType();

    <R> T adapt(Call<R> var1);

    主要作用是将Call对象转换成别的对象,有一个默认实现类DefaultCallAdapter

  • Callback

    这个接口就是retrofit请求数据返回的回调

    • void onResponse(Response response);
    • void onFailure(Throwable t);
  • Converter

    这个接口主要的作用就是将HTTP返回的数据解析成Java对象,主要由Xml、Gson、protobuf等等,你可以在创建Retrofit对象时添加你需要使用的Converter实现

  • DefaultCallAdapterFactory

    CallAdapter的默认实现类的工厂类

  • ExecutorCallAdapterFactory

    Call执行时的工厂类

  • OkHttpCall

  • ParameterHandler

    主要用于将声明接口中的参数进行翻译

  • Platform

    查找运行平台的类,平台包括:ios、android、java8

  • RequestBuilder

    用于请求的构建

  • Response

  • Retrofit

  • ServiceMethod

    主要用于将用注解声明的接口方法进行翻译

  • Utils

    工具类

深入源码

首先通过Retrofit.Builder创建Retrofit实例
我们可以看到Retrofit.Builder中定义了如下变量:

private Platform platform;    //运行平台
// okhttp3 的网络请求工厂
private okhttp3.Call.Factory callFactory; 
private HttpUrl baseUrl; // 网络请求地址的基础部分(公共部分),Retrofit会自动拼接成真正的请求地址
private List<Converter.Factory> converterFactories = new ArrayList<>();
    private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
private Executor callbackExecutor; // 回调的执行器
// 这个是设置的在创建动态代理对象之前,
//若为真,会调用eagerlyValidateMethods方法,提前加载serviceMethod
private boolean validateEagerly;

Retrofit.Builderbuild()方法:

public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

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

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

      // 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()方法,可以得知Retrofit在build的时候会提供一个默认的CallAdapterFactory

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

CallAdapterFactory有两种情况:

  1. callbackExecutor 为空的时候返回的是DefaultCallAdapter.FACTORY,这个DefaultCallAdapter.FACTORY返回一个DefaultCallAdapter

    //如果在android平台上的话,当callbackExecutor为空会直接使用handler将结果返回到主线程(MainThread)
    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);
          }
        }
      }
    
  2. callbackExecutor不为空的时候返回ExecutorCallAdapterFactory,这个Factory返回的CallAdapterExecutorCallbackCall

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

    //异步回调,通过简单的修饰callback,再用callbackExecutor执行真正的回调
    //这样回调可以在线程中执行并使用callbackExecutor管理。
    @Override public void enqueue(final Callback<T> callback) {
      if (callback == null) throw new NullPointerException("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 boolean isExecuted() {
      return delegate.isExecuted();
    }

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

    @Override public void cancel() {
      delegate.cancel();
    }

    @Override public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override public Call<T> clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override public Request request() {
      return delegate.request();
    }
  }

retrofit实例完成后,通过调用create(CyyHttpService.class)方法传入定义的接口CyyHttpService,然后实现“动态代理”CyyHttpService。

关于动态代理:简单来说Java动态代理就是当你要调用某个类的方法前,插入你想要执行的代码。比如你要执行某个操作前,你必须要判断这个用户是否登录。)

 public <T> T create(final Class<T> service) {
     //首先调用validateServiceInterface方法判断是否这个对象是一个接口对象
    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, Object... args)
              throws Throwable {
            if(method.getDeclaringClass() == Object.class) {
                    return method.invoke(this, args);
                } else if(this.platform.isDefaultMethod(method)) {
                    return this.platform.invokeDefaultMethod(method, service, proxy, 
                                                              args);
                } else {
                    ServiceMethod serviceMethod = 
                                  Retrofit.this.loadServiceMethod(method);
                    OkHttpCall okHttpCall = new OkHttpCall(serviceMethod, args);
                    return serviceMethod.callAdapter.adapt(okHttpCall);
                }
        });
  }
CyyHttpService service = retrofit.create(CyyHttpService.class);
Call<ResponseBody<String>> total = service.getTotal("token");

当执行service.getTotal("token")的时候,就会通过InvocationHandler.invoke()来执行loadServiceMethod()。

ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

上面是对通过注解定义的接口方法进行构建,并存入缓存当中。

通过OkHttpCall okHttpCall = new OkHttpCall(serviceMethod, args)将其包装成okhttp请求。然后通过calladapter对其进行处理。

执行total.enqueue()方法时,通过OkHttpCall将Http请求返回数据并解析成实体,在回调中返回。

@Override public void enqueue(final Callback<T> callback) {
    if (callback == null) throw new NullPointerException("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 {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

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

    if (canceled) {
      call.cancel();
    }

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

当执行到call = rawCall = createRawCall();时,会构建一个相对应的请求对象Call。

private okhttp3.Call createRawCall() throws IOException {
    Request request = serviceMethod.toRequest(args);
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

当请求得到响应后,执行response = parseResponse(rawResponse);进行解析。

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

正常流程下,将会进行到如下片段:

T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);

toResponse方法:

T toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }

通过responseConverter.convert()方法解析之后就会获得当初声明的返回类型。

然后执行return Response.success(body, rawResponse);

至此整个请求流程执行完毕。

版权声明:

本文标题:Retrofit源码分析

作者:Rabtman

原始链接:https://rabtman.com/2016/07/30/retrofit2_source_analysis/

本文采用署名-非商业性使用-禁止演绎4.0进行许可。

非商业转载请保留以上信息。商业转载请联系作者本人。