A brief analysis of the demolition of the wheels [series] Retrofit source

The project is now used in the Retrofit for network requests, so I spent some time analyzing its source code, now do a brief analysis.

Overall, Retrofit uses dynamic proxy mode, it is not a final request to the network, the network is a real request OkHttp. Here, do not do a detailed analysis, I plan a reanalysis next.

Take a look at its overall flow
Retrofit overall process

We look at the normal use Retrofit, then combined on chart analysis.

    Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(sOkHttpClient)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

This is normal configuration

1. In the source Retrofit.Buidler () in

 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) {
        // 根据 platform, 选择不同的 CallbackExecutor
        // 这里是 platform 是 Android , 返回的是 MainThreadExecutor;
        //  MainThreadExecutor 类,内部是通过 Handler 将 Runnable post 回主线程执行
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      // adaperFactories 是用来在存放 CallAdapterFactory, 例如使用 RxJavaCallAdapterFactory, 也会添加进来
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      //defaultCallAdapterFactory 是 ExecutorCallAdapterFactory,其中 MainThreadExcutor 作为参数构造
      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);
    }

Detailed analysis see the comment;

2. Retrofit.create()

Using dynamic proxy mode In this method, see the proxy mode and the dynamic proxy mode ,

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    // 动态代理, 返回一个 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 the method is a method from Object then defer to normal invocation.
            // 如果该方法只是对象的普通方法,这直接调用
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }

            // 默认是 false
            if (platform.isDefaultMethod(method)) {
                return platform.invokeDefaultMethod(method, service, proxy, 
                                                                      args);
            }

            // ServiceMethod 调用接口的方法,转变成一个 Http Call
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);

            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            // serviceMethod.callAdapter 返回是 默认ExecutorCallAdapterFactory
            // &ExecutorCallbackCall
            // 如果添加了 RxJavaCallAdapter, 返回的是 RxJavaCallAdapter
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

3. ServiceMethod.build()

The main job of the three-point method

  • Retrofit.build removed in CallAdapter, for example, is arranged above RxJavaCallAdapterFactory, the resultant is RxJavaCallAdapter;
  • Retrofit.build taken in responseConverter, for example, is arranged above GsonConverterFactory, is obtained GsonResponseBodyConverter.
  • Notes analytical method
public ServiceMethod build() {
      // 创建 CallAdapter, 其实是返回 Retrofit 中的 callAdapter,
      // ExecutorCallAdapterFactory$ExecutorCallbackCall
      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?");
      }
      // 返回 Retrofit.responseBodyConverter(...), 其实是从 converterFactories 中取出 ResponseBodyConverter
      //  例如,如果配置了 GsonResponseBodyConverter, 则返回.
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        // 解析注解方法,
        //@GET("group/{id}/users")
        //Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
        // 中的 @GET("group/{id}/users")
        parseMethodAnnotation(annotation);
      }

    // 省略后面
    .... 
}

Retrofit of execution

performing a synchronous method call and an asynchronous method
synchronous call.execute ()
Asynchronous call.enqueue (Callback callback);
here synchronized Example
Operative

1. OkHttpCall.execute

// 同步执行
  @Override
  public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
     // 省略
    ...
      call = rawCall;
      if (call == null) {
        try {
          // 创建 Call
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
      }
    }

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

    // 发起请求,并解析返回结果
    // 这里的 call 是 OkHttp 中的 RealCall
    return parseResponse(call.execute());
  }

2. OkHttpCall.createRawCall

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

3. OkHttCall.parseResponse

Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
    // 省略
   ....

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      // T 是想要的结果,例如  Call<List<Repo>> listRepos(@Path("user")
      // String user); 中的 List<Repo>
      T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
     // 省略
     ...
    }
  }

3. ServiceMethod.toResponse

 /** Builds a method return value from an HTTP response body. */
  R toResponse(ResponseBody body) throws IOException {
    // responseConverter 是 Retrofit 中配置的 Conveter
    return responseConverter.convert(body);
  }

Examples of the above configuration is Conveter GsonConverter, therefore, resonseConverter here is GsonResponseConverter.

If we convert Http results returned Java objects you want, we must implement the Converter interface, but also to achieve RequestConverter and ReponseConverter specific implementations Gson conversion method may reference source.

At this point, Retrofit basic source code analysis is complete.
Comment has been uploaded to GitHub RetrofitAnnotions

Personally I think a lot of knowledge can be learned:

  1. Retrofit using Build mode, in fact, many have used the open source library, you can look at specific "Effective Java" in the relevant section, which has detailed description;

  2. Retrofit using the constructor Collection.unmodifiableList (list) method, such a return may traverse the List only, but can not be modified List;

  3. It uses dynamic proxy mode;

  4. Detect whether a class is Interface, you can call class.isInterface.
    utils.java in

 static <T> void validateServiceInterface(Class<T> service) {
    if (!service.isInterface()) {
      throw new IllegalArgumentException("API declarations must be interfaces.");
    }
    // Prevent API interfaces from extending other interfaces. This not only avoids a bug in
    // Android (http://b.android.com/58753) but it forces composition of API declarations which is
    // the recommended pattern.
    if (service.getInterfaces().length > 0) {
      throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
    }
  }

** Reference Articles
these articles are good, it is recommended to see. **

  1. Demolition wheel series: demolition Retrofit
  2. Retrofit2 source parsing
Published 58 original articles · won praise 20 · views 90000 +

Guess you like

Origin blog.csdn.net/yxhuang2008/article/details/56342639