Introduction Retrofit is an HTTP framework launched by Square, mainly used in Android and Java. Retrofit converts network requests into method calls, which is very simple and convenient to use. This article first briefly introduces the usage of Retrofit, and then specifically analyzes the execution process of its source code. Basic Usage Retrofit turns HTTP API into Java interface. Here is an example from Retrofit official website:
In the GithubService interface, there is a method listRepos, which is annotated with @GET, indicating that this is a GET request. The users/{user}/repos in the brackets at the end is the path of the request, where {user} indicates that this part is dynamically changing, and its value is passed by the method parameter, and the parameter @Path("user") String user of this method is used to replace {user}. Also note that the return value of this method is Call<List<Repo>>. It can be seen that Retrofit uses annotations to describe the parameters related to a network request. The above is just the beginning. Now we need to make this network request:
It can be seen that a Retrofit object is first constructed, in which the baseUrl parameter is passed in. The baseUrl and the path after the above GET method are combined to form a complete URL. In addition to baseUrl, there is also a converterFactory, which is used to convert the returned http response into a Java object, corresponding to the return value of the method Call<List<Repo>> in List<Repo>>, where Repo is a custom class. With the Retrofit object, call its create method to create an instance of GitHubService, and then call the method of this instance to request the network. Call the listRepo method to get a Call object, and then use enqueue or execute to initiate the request. enqueue is asynchronous execution, while execute is synchronous execution. This is the basic usage of Retrofit. For other details, please check the official website. Source code analysis When I first came into contact with Retrofit, I thought it was quite magical, and its usage was different from general network requests. Let's take a look at how the source code of Retrofit is implemented. Retrofit creation From the creation method of Retrofit, we can see that the Builder mode is used. There are several key variables in Retrofit:
Let's take a look at the builder method of the inner class Builder in Retrofit:
When creating Retrofit, if OkHttpClient is not specified, a default one will be created. If callbackExecutor is not specified, the platform default will be returned, which is MainThreadExecutor in Android, and a CallAdapter will be built using this to add to adapterFactories. create method Once you have a Retrofit object, you can create an instance of the network request interface class through the create method. The code is as follows:
The create method accepts a Class object, which is the interface we wrote, which contains the method for requesting the network marked by annotations. Note the return statement part, where the Proxy.newProxyInstance method is called. This is very important because the dynamic proxy mode is used. For more information about the dynamic proxy mode, you can refer to this article: http://www.codekk.com/blogs/d... A simple description is that Proxy.newProxyInstance generates an instance A, which is the proxy class, based on the Class object passed in. Whenever this proxy class A executes a method, it always calls the invoke method of InvocationHandler (the third parameter in Proxy.newProxyInstance). In this method, you can perform some operations (here, the annotation parameters of the parsing method, etc.), and through this method, the network request in the interface we wrote is actually executed. Method resolution and type conversion Let's take a closer look at the lines in invoke that parse the network request method. First, ServiceMethod serviceMethod = loadServiceMethod(method);, where the loadServiceMethod code is as follows:
It can be seen that the cache is searched first, and no further creation is done in the cache. A ServiceMethod object is created here. ServiceMethod is used to convert the call of the interface method into an HTTP request. In fact, in ServiceMethod, the annotations and parameters of the method in the interface are parsed, and it also has a toRequest method to generate a Request object. This Request object is the Request in OkHttp, which represents a network request (Retrofit actually entrusts the actual network request operation to OkHttp for execution). The following is part of the code to create ServiceMethod:
After getting the ServiceMethod object, pass it and the relevant parameters of the method call to the OkHttpCall object, which is this line of code: OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);. The following introduces OkHttpCall, which inherits from the Call interface. Call is the basic interface of Retrofit, representing sending network requests and response calls. It contains the following interface methods:
OkHttpCall is an implementation class of Call, which encapsulates the native Call in OkHttp. Methods such as execute and enqueue are implemented in this class, which actually calls the corresponding methods of the native Call in OkHttp. Next, pass OkHttpCall to the serviceMethod.callAdapter object. What is callAdapter here? In the code that creates ServiceMethod above, there is a line of code: callAdapter = createCallAdapter(). Here, calladapter is created. Inside this code, the corresponding CallAdapter is found based on the return type and annotation of the method. Where to find it? Find it in the adapterFactories collection of the Retrofit object. When we create Retrofit, we can call addCallAdapter to add CallAdapter to adapterFactories. In the previous basic usage, we did not add any CallAdapter, but an ExecutorCallAdapterFactory will be added to adapterFactories by default. Calling its get method can get the CallAdapter object. So what does CallAdapter do? The adapt method is called above, which is to convert a Call to another type. For example, when Retrofit is used in combination with RxJava, the method in the interface can return Observable<T>, which is equivalent to the adapter pattern. By default, a Call object is obtained, which is ExecutorCallbackCall. The code is as follows:
This ExecutorCallbackCall accepts a callbackExecutor (MainThreadExecutor by default in Android, which passes the returned data back to the main thread) and a call, which is OkhttpCall. Look at the ExecutorCallbackCall code:
In the enqueue method, the enqueue of OkHttpCall is called, so this is equivalent to the static proxy mode. The enqueue in OkHttpCall actually calls the enqueue in the native OkHttp, where the network request is actually issued. Some of the code is as follows:
After OkHttp obtains the data, it parses the data and calls back the callback response method, and a network request is completed. Summarize The code of the entire Retrofit framework is not too long and is relatively easy to read. It mainly uses dynamic proxy to parse the Java interface into the corresponding network request, and then sends it to OkHttp for execution. It can also adapt to different CallAdapters and can be easily used in combination with RxJava. |
<<: Let’s take a look at BAT’s layout in the AR field. How would you rate it?
>>: As tech giants race to seize the VR virtual reality market, has Google taken the lead?
When it comes to system support for older phones,...
1. Introduction to Wenchang Tower Wenchang Pagoda...
You can drive the car home without spending a pen...
[51CTO.com original article] What are the data re...
According to a report by The Verge, a Windows 10 ...
Now more and more friends are joining the ranks o...
Introduction: Whether it is a large company or a ...
1. "Earthquake Cloud" predicted the ear...
When it comes to Tibetan antelopes, everyone prob...
The Dragon Boat Festival is coming soon, and many...
Gaopengquan knowledge paid micro-course platform ...
The Nobel Prize ceremony in 1906 was a lively and...
Mini Programs are a new way to attract new users....
HTC released a number of new products in New York...
The annual grand "human migration" - Sp...