Retrofit2源码阅读

来源:互联网 发布:未转变者服务器端口 编辑:程序博客网 时间:2024/06/06 00:42

Retrofit2源码阅读(版本:com.squareup.retrofit2:retrofit:2.3.0)

retrofit_stay.png
这个图来自trello,貌似一个叫Stay的大佬做的?感谢大佬。
用一个网络请求的流程来分析阅读,以simples包下的SimpleService为例:

  // Create a very simple REST adapter which points the GitHub API.  // https://api.github.com/repos/square/retrofit/contributors    Retrofit retrofit = new Retrofit.Builder()        .baseUrl(API_URL)        .addConverterFactory(GsonConverterFactory.create())        .build();    // Create an instance of our GitHub API interface.    GitHub github = retrofit.create(GitHub.class);    // Create a call instance for looking up Retrofit contributors.    Call<List<Contributor>> call = github.contributors("square", "retrofit");    // Fetch and print a list of the contributors to the library.    List<Contributor> contributors = call.execute().body();   .....

addConverterFactory方法加入一个Converter工厂,如retrofit2.converter.gson.GsonConverterFactory.

    public Builder addConverterFactory(Converter.Factory factory) {      converterFactories.add(checkNotNull(factory, "factory == null"));      return this;    }

retrofit2.Retrofit.Builder#build:

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

调用retrofit2.Retrofit#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 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);            }            ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) loadServiceMethod(method);            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);            return serviceMethod.callAdapter.adapt(okHttpCall);          }        });  }

retrofit2.Retrofit#loadServiceMethod会去serviceMethodCache根据method查找ServiceMethod,如果没有查到,就根据Retrofit对象和method创建一个ServiceMethod(把接口方法的调用适配为一个Http call)。以Method为key,ServiceMethod为value的放入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 = new ServiceMethod.Builder<>(this, method).build();        serviceMethodCache.put(method, result);      }    }    return result;  }

retrofit2.ServiceMethod#toRequest:

/** Builds an HTTP request from method arguments. */  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();  }

retrofit2.OkHttpCall#createRawCall:根据url的参数生成Okhttp3的request ,和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;  }

okhttp3.RealCall#execute:

  @Override public Response execute() throws IOException {    synchronized (this) {      if (executed) throw new IllegalStateException("Already Executed");      executed = true;    }    captureCallStackTrace();    try {      client.dispatcher().executed(this);      Response result = getResponseWithInterceptorChain();      if (result == null) throw new IOException("Canceled");      return result;    } finally {      client.dispatcher().finished(this);    }  }

retrofit2.OkHttpCall#parseResponse,根据T转化为ArrayList。

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) {      rawBody.close();      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;    }  }

retrofit2.ServiceMethod#toResponse:

  /** Builds a method return value from an HTTP response body. */  R toResponse(ResponseBody body) throws IOException {    return responseConverter.convert(body);  }

这里因为之前传入的是retrofit2.converter.gson.GsonConverterFactory,由retrofit2.Converter.Factory#responseBodyConverter获得retrofit2.converter.gson.GsonResponseBodyConverter,把ResponseBody 转化为ArrayList返回。ok,完整的一个请求流程就是这些。

原创粉丝点击