Retrofit is widely used in Android, and it’s important to understand how it works so that you can extend it. If you encounter problems, read the source code. First let’s take a look at the basic steps.

Retrofit integrates basic use of RxJava

Network requests can be made with simple configuration. Now let’s analyze the specific principles.

1. Generate proxy objects

We use Retrofit.create () as the entry point for analysis, which transforms the interface configured for the network request into an object that implements that interface. The core technology is JDK dynamic proxy

Here we need to understand two things:

Retrofit uses JDK dynamic proxy technology to generate a proxy object that implements the ApiService interface. The invoke() method of the ApiService interface executes the invoke() method of the InvocationHandler, which returns a bServable object. The create() method is simpler.

It ultimately returns an 0bServable object, which organizes the network request, parses the response, and sends the response to the 0bServer subscribing to 0BServable

Here we need to break it down into two steps: what loadServiceMethod() and invoke() do.

2. Preparation stage of network request

The main task of loadServiceMethod() is to parse the annotation information on the network request interface method, get the data adapter, the data parser object, and finally wrap the ServiceMethod object back.

Obviously, the emphasis is on parseAnnotations() :

RequestFactory. ParseAnnotations (retrofit, method) is an important step, it will go to parse ApiService annotations on the corresponding methods in the information and parameters on the annotation information, prepare the necessary information network request.

Next, I call parseAnnotations() of HttpServiceMethod, which inherit from ServiceMethod:

The RxJava data adapter and Gson parser factory were set up when the Retrofit object was created. Now we need to get the corresponding data adapter and parser from the factory, and finally encapsulate the data into CallCaller.

HttpServiceMethod also overrides the invoke() method of ServiceMethod:

Its adapt method ends up calling the RxJava data adapter’s adapt() method:

At this point, the execution of the loadServiceMethod() method ends and returns a CallStuck object that inherits HttpServiceMethod. The OkHttpCall, data adapter, and data parser are also ready.

Based on the previous analysis, the invoke() method that calls ServiceMethod ends up calling the ADAPT () method of the RxJava data adapter with the argument OkHttpCall.

Data adapter object through the data adapter factory RxJava2CallAdapterFactory created:

So the adapt() method returns an Observable, but that’s still too rough, and we need to dig a little deeper.

According to the above analysis, the responseObservable object should be obtained by executing new CallExecuteObservable<>(call), and then executing new BodyObservable<>(responseObservable). To further encapsulate it, let’s look at how the CallExecuteObservable class is implemented:

The core of the CallExecuteObservable class is the subscribeActual() method, which is executed when the Observer subscribes to an Observable, that is, the subscribe() method is called. The network request is made in the subscribeActual() method and the result is passed to the Observer.

So why does the BodyObservable class further encapsulate responseObservable? Go inside and find the answer:

As you can see, the main function of the BodyObservable class is to enhance our custom observer function through the BodyObserver class. So that it can further process the response result obtained by observer.onNext(response) in CallExecuteObservable, and only extract the data of the response body and send it to our customized observer.

At this point, the primary task of the data adapter is to prepare for RxJava integration by calling Retrofit’s encapsulated OkHttpCall to perform the network request and sending the results to the Observer.

One thing we don’t know is what OkHttpCall, which executes its call.execute() method in CallExecuteObservable, does internally and how it makes network requests through OkHttp.

The OkHttpCall execute() method is relatively simple:

So OkHttpCall’s execute() method internally builds OkHttp’s Call object and initiates network requests, but why synchronous requests? Because we’ve used RxJava to switch to child threads. So Retrofit is linked to OkHttp.

5. The purpose of the data parser OkHttpCall’s parseResponse() is to use Gson to convert the JSON string of the response body into the specified object.

Key is responseConverter. Convert (catchingBody), through the configuration Settings when the Retrofit responseConverter GsonConverterFactory data parser factory, The corresponding data parser is GsonRequestBodyConverter:

The response body is parsed through Gson and converted into an object of the specified type. If the response body is encrypted, you can do the decryption work here and then the Gson parsing.

Retrofit allows developers to describe web requests in the form of interface annotations, then parse the interface and encapsulate web requests in OkHttpCall. The data adapter uses Retrofit’s OkHttpCall to organize network requests. It’s up to you to play with the data adapter. The data parser is relatively simple, converting the results of the network request into the desired format. The responsibilities of Retrofit, data adapter, and data parser are clearly delineated, there is little business coupling, and they are completely pluggable.