An overview of the

Retrofit is a type-safe network request framework for the Android and Java platforms. Retrofit is an encapsulation of a RESTful HTTP Web request framework. Network request work is essentially done by OkHttp, while Retrofit is only responsible for encapsulating the network request interface, which can be used in combination with Rxjava, coroutines, and LiveData. The serialized data returned can be Gson, Jackson, Moshi, Protobuf, and so on

The source code to use

Create and use

Also created from the schema Builder, you can specify BaseUrl, OkHttpClient, adapter, and sequence number factory

  1. Create a Retrofit
 Retrofit retrofit=new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(new OkHttpClient())
                // Specify the Rxjava adapter
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                // Specify the serialization structure
                .addConverterFactory(GsonConverterFactory.create())
                .build();

Copy the code
  1. Create the interface
public interface ApiService {
    @GET("/wxarticle/list")
    Call<ResponseBody> getNetData(a);
    @GET("/wxarticle/list")
    Observable<ResponseBody> getNetData2(a);
}
Copy the code
  1. request
 / / create ApiService
 ApiService apiService = retrofit.create(ApiService.class);
 // Use the original built-in request
  retrofit2.Call<NetData> netData = apiService.getNetData();
  netData.enqueue(new retrofit2.Callback<NetData>() {
      @Override
      public void onResponse(retrofit2.Call<NetData> call, retrofit2.Response<NetData> response) {}@Override
      public void onFailure(retrofit2.Call<NetData> call, Throwable t) {}});// ADAPTS the request to the Rxjava stream
  apiService.getNetData2()
          .subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe(data -> {
          }, error -> {
          });
Copy the code

parsing

Create the Builder.build method for Retrofit

 public Retrofit build(a) {
    if (baseUrl == null) {
      throw new IllegalStateException("Base URL required.");
    }
	// The factory mode is used here, but only an OkHttpClient is new
    okhttp3.Call.Factory callFactory = this.callFactory;
    if (callFactory == null) {
      callFactory = new OkHttpClient();
    }

    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {
    // Because in Android platform is Android, platform is an internal class android
      callbackExecutor = platform.defaultCallbackExecutor();
    }

    // This is to add all adapters. The adapter pattern used here is to adapt calls from Okhttp to Retrofit
    / / can also add our own adapter, such as RxJava2CallAdapterFactory. The create (), Rxjava.
    // You can also add coroutines or LiveData
    
    List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
    callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

    // This is a javabean conversion class, Gson, Moshi, Protobuf,
    List<Converter.Factory> converterFactories =
        new ArrayList<>(
            1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

    converterFactories.add(new BuiltInConverters());
    converterFactories.addAll(this.converterFactories);
    converterFactories.addAll(platform.defaultConverterFactories());
 // Implement Retrofit constructors
    return new Retrofit(
        callFactory,
        baseUrl,
        unmodifiableList(converterFactories),
        unmodifiableList(callAdapterFactories),
        callbackExecutor,
        validateEagerly);
  }
  
 // Create the APIService, using the dynamic proxy mode, creating an object at run time
public <T> T create(final Class<T> service) {
    validateServiceInterface(service);
    return (T)
        Proxy.newProxyInstance(
            service.getClassLoader(),
            newClass<? >[] {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 it comes from the Object method, continue with the original logic
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args); } args = args ! =null ? args : emptyArgs;
                 The isDefaultMethod() method returns false by default on Android. Because we're using the method in the interface
                 // The default method in the interface is not called
                 //Java 8 introduces a new language feature, Default Methods
                 // Invoke loadServiceMethod(method).invoke(args)
                returnplatform.isDefaultMethod(method) ? platform.invokeDefaultMethod(method, service, proxy, args) : loadServiceMethod(method).invoke(args); }}); }// return a ServiceMethod and execute the methodServiceMethod<? > loadServiceMethod(Method method) {// Take it from the cache first, return it directlyServiceMethod<? > result = serviceMethodCache.get(method);if(result ! =null) return result;
  synchronized (serviceMethodCache) {
    result = serviceMethodCache.get(method);
    if (result == null) {
     // Use reflection, so cache a copy
     // HttpServiceMethod, a subclass of ServiceMethod, is returned
      result = ServiceMethod.parseAnnotations(this, method); serviceMethodCache.put(method, result); }}return result;
}
Copy the code

HttpServiceMethod: Retorfit annotation parameters and urls are converted to Okhttp Requst, there are respones that come back, and there are requests that are adapted here, and adapted to various return values. By default, Okhttp calls are adapted to Retrofit calls. Or Rxjava Observables, or coroutines, and serializations are all transformed here

Look at the request, look at the default, don’t look at Rxjava, look at how Retrofit calls are converted to Okhttp calls

When we execute, we go to invoke in HttpServiceMethod

abstract class HttpServiceMethod<ResponseT.ReturnT> extends ServiceMethod<ReturnT> {
  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) {
      // Is the coroutine method in Kotlin
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;
	// Get all the annotations
    Annotation[] annotations = method.getAnnotations();
    // Get the return type
    Type adapterType;
    // The coroutine,
    if (isKotlinSuspendFunction) {
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType =
          Utils.getParameterLowerBound(
              0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
        // Unwrap the actual body type from Response<T>.
        responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
        continuationWantsResponse = true;
      } else {
      }

      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
    // Get the return type
      adapterType = method.getGenericReturnType();
    }

 // This will go to Retrofit's nextCallAdapter method, which iterates through the collection of adapters we set up to get the return type
    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
      // Get the return serialization type, which is used to find the serialization method
    Type responseType = callAdapter.responseType();
    if (responseType == okhttp3.Response.class) {
         }
    if (responseType == Response.class) {
      throw methodError(method, "Response must include generic type (e.g., Response<String>)");
    }
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }

 // Get the converterFactories collection that you set up
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if(! isKotlinSuspendFunction) {// Call Best-in-line (undefined) call best-in-line (undefined) call best-in-line (undefined)
      return newCallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter); }}}Copy the code

The OkHttpCall encapsulates the Okhttp Call. When we call the request, we are actually calling the Okhttp request

final class OkHttpCall<T> implements Call<T> {
@Override
  public void enqueue(final Callback<T> callback) {
    Objects.requireNonNull(callback, "callback == null");
	// Get the Okhttp call
    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 {
         // The new Call from OkhttpClient is used by default. As described above, the factory is used, but the OkhttpClient is still new
          call = rawCall = createRawCall();
        } catch(Throwable t) { throwIfFatal(t); failure = creationFailure = t; }}}// Invoke the request
    call.enqueue(
        new okhttp3.Callback() {
          @Override
          public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
            Response<T> response;
            try {
            // After the request succeeds, the request is parsed and the actual lock is returned
              response = parseResponse(rawResponse);
            } catch (Throwable e) {
              throwIfFatal(e);
              callFailure(e);
              return;
            }
          private void callFailure(Throwable e) {
            try {
              callback.onFailure(OkHttpCall.this, e);
            } catch (Throwable t) {
                          t.printStackTrace(); // TODO this is not great}}}); }}// Parse the return value
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
 try {
   // responseConverter is the default converter, and GsonRequestBodyConverter can be serialized to the corresponding format
      T body = responseConverter.convert(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();
      throwe; }}Copy the code