Retrofit request annotation
Serial number | name | explain |
---|
1 | GET | get request |
2 | POST | post request |
3 | PUT | put request |
4 | DELETE | delete request |
5 | PATCH | patch request, which is a supplement to put request and is used to update local resources |
6 | HEAD | head request |
7 | OPTIONS | option request |
8 | HTTP | The general annotation can replace all the above annotations. It has three attributes: method, path and hasBody |
Retrofit Parameter annotation
classification | name | explain |
---|
Act on method | Headers | It is used to add fixed request headers. Multiple can be added at the same time. The request headers added through this annotation will not overlap each other, but exist together |
Parameters acting on method parameters | Header | Passed as a parameter of the method, it is used to add an unfixed Header. This annotation will update the existing request Header |
Request parameters | Body | It is mostly used for sending non form data in post request, such as transferring json format data in post mode |
Request parameters | Field | You need to use the fields of URL and fileencoded in the request form to add multiple fields |
Request parameters | FieldMap | Form fields, together with Field and FormUrlEncoded, receive map < String, String > types. Non String types will call toString() method |
Request parameters | Part | It is used for form fields. Part, PartMap and Multipart annotations are used together. It is suitable for file upload |
Request parameters | PartMap | The form field, matched with Part, is suitable for file upload. By default, it receives the type of map < string, RequestBody >, and non RequestBody will be converted through Converter |
Request parameters | HeaderMap | Used for URL, add request header |
Request parameters | Path | It is used as a placeholder in the url. The path has parameters, such as project/{id}/list. Where id is a placeholder parameter, use @ Path("Id") id:Int to complete the parameter |
Request parameters | Query | Used to set parameters in Get request |
Request parameters | QueryMap | Similar to Query |
Request parameters | Url | Specify the path of the request |
Retrofit tag annotation
classification | name | explain |
---|
Request parameters | FormUrlEncoded | Indicates that the request entity is a Form, and each key value pair needs @ Field annotation |
Request parameters | Multipart | Indicates that the requesting entity is a Form that supports file upload and needs to be used together. @ Part is applicable to scenarios with file upload |
sign | Streaming | The data representing the response body is returned in the form of stream, which is applicable to the large returned data. This annotation is particularly useful when downloading large files |
- Usage of uploaded files @ Multipart annotation
interface AndroidApi {
//Upload pictures
@Multipart
@POST("project/upload")
fun upload(@Part file: MultipartBody.Part): Call<RequestBody>
//Upload multiple pictures
@Multipart
@POST("project/upload")
fun uploadMulti(@PartMap map: Map<String, MultipartBody.Part>): Call<RequestBody>
}
//Single picture upload
fun testUpload(path: String) {
val file = File(path)
val requestBody = file.asRequestBody("image/png".toMediaTypeOrNull())
val filePart = MultipartBody.Part.createFormData("key", file.name, requestBody)
val call = androidApi.upload(filePart)
call.execute()
}
//Multi map upload
fun testUploadMulti(files: List<File>) {
val map = mutableMapOf<String, RequestBody>()
files.forEach { file ->
val requestBody = file.asRequestBody("image/png".toMediaTypeOrNull())
map["file\";filename=\"test.png"] = requestBody
}
androidApi.uploadMulti(map)
}
interface AndroidApi {
//The data representing the response body is returned in the form of stream, which is applicable to large returned data. This annotation is particularly useful when downloading large files
@Streaming
@GET
fun downloadFile(@Url fileUrl:String):Call<RequestBody>
}
Annotation by reflection
- First, use the isAnnotationPresent() method of the Class object to determine whether it applies an annotation
javaClass.isAnnotationPresent(Nullable::class.java)
- Then get the Annotation object through getAnnotation() or getAnnotations() methods
Parsing process of Retrofit annotation
- Use the code on the process
private fun retrofitTest() {
//Generate retrofit instance
val retrofit = Retrofit.Builder()
.baseUrl("http://image.so.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
//Create apiService instance
val realApi = retrofit.create(RealApi::class.java)
//Request specific interface
realApi.getPicData(name, startNum, pageNum)
.enqueue(object : Callback<RealPic?>() {
fun onResponse(call: Call<RealPic?>?, response: Response<RealPic?>) {
}
fun onFailure(call: Call<RealPic?>?, t: Throwable?) {
}
})
}
- Retrofit.Builder
Creating Retrofit objects through builder mode - Retrofit.create
Pass in a custom interface service, including methods and annotations
Create an instance proxy of the interface through dynamic proxy newProxyInstance - loadServiceMethod
Through reflection, the defined annotation is parsed to generate a ServiceMethod object and cached
Parsing of RequestFactory annotation
Assemble the RequestBuilder annotation and assemble it as the Request of OKhttp - new OkHttpCall<>
Create OkHttpCall object, implement call interface and adapt okhttp3 Call - T adapt(Call<> call)
Take the CallAdapter from the callAdapterFactories collection of Retrofit and call the adapt method. If it is the default, use ExecutorCallAdapterFactory to adapt and return call < >. If it is RxJavaCallAdapterFactory, return Observable - enqueue
Execute the specific request. After the request is completed, submit the Runnable to the main thread through the mainthreadexecution
Subsystem provided by Retrofit (appearance mode)
- serviceMethodCache (custom interface mapping object collection)
- baseUrl (request address)
- callFactory (OKHttpCall by default)
- converterFactories (data parser factory collection)
- callAdapterFactories (collection of Call adapter factories)
- callbackExecutor (callback execution, mainthreadexecution by default for Android platform)
- Using the Builder model to build, the parts that the object depends on are created, assembled and encapsulated, so that the client can easily obtain a complex object.
ServiceMethod
- ServiceMethod is a request method in an interface
- For the network Request object mapped by the interface, the label of the user-defined interface is converted into the object through the dynamic agent, and the label and parameters are generated into the Request object required by OkHttp. Retrofit.create intercepts through dynamic proxy, converts each custom interface method into a ServiceMethod object, and caches it through ServiceMethodCache.
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[] {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 the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}