1 Introduction
Retrofit is a framework developed by Android Square's network of HTTP requests, the official website is https://square.github.io/retrofit/ . The bottom layer is based on OkHttp, which means Retrofit further encapsulates OkHttp. The biggest feature of Retrofit is simplicity and ease of use. It uses a large number of runtime annotations to provide functions.
2 Quick start
Suppose there is a server interface: https://api.xx.com/url.json?id=123 , and the return value after the request is
[
{
"app_name": "今日头条",
"package_name": "com.ss.android.article.news"
},
{
"app_name": "腾讯新闻",
"package_name": "com.tencent.news"
},
{
"app_name": "凤凰新闻",
"package_name": "com.ifeng.news2"
}
]
Now we need to make a network request for it in the code and convert the returned result into an AppInfo object. The AppInfo class code is as follows:
AppInfo.java
public class AppInfo {
private String app_name;
private String package_name;
@Override
public String toString() {
return "{app_name:" + app_name + ",package_name:" + package_name + "}";
}
}
Add support library dependency in build.gradle:
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.6.2'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
}
Declare the network request permission in AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET"/>
So we use Retrofit to make network request code like this:
private void getRequest() {
Retrofit retorfit = new Retrofit.Builder()
.baseUrl("https://api.xx.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
AppInfoService appInfoService = retorfit.create(AppInfoService.class);
Call<List<AppInfo>> call = appInfoService.getAppInfoList(123);
call.enqueue(new Callback<List<AppInfo>>() {
@Override
public void onResponse(Call<List<AppInfo>> call, Response<List<AppInfo>> response) {
List<AppInfo> appInfos = response.body();
Log.e("zyx", appInfos.toString());
Log.e("zyx", "当前线程:" + Thread.currentThread().getName());
}
@Override
public void onFailure(Call<List<AppInfo>> call, Throwable t) {
Log.e("zyx", t.toString());
Log.e("zyx", "当前线程:" + Thread.currentThread().getName());
}
});
}
public interface AppInfoService {
@GET("url.json")
Call<List<AppInfo>> getAppInfoList(@Query("id") int id);
}
Execute the getRequest method in your code, run the program, you can see the output of the following results, and the callback will also be performed in the main thread:
2019-12-04 19:27:23.209 30842-30842/com.zyx.myapplication E/zyx: [{app_name:今日头条,package_name:com.ss.android.article.news}, {app_name:腾讯新闻,package_name:com.tencent.news}, {app_name:凤凰新闻,package_name:com.ifeng.news2}]
2019-12-04 19:27:23.212 30842-30842/com.zyx.myapplication E/zyx: 当前线程:main
3 Introduction
3.1 Library dependencies and converters
To use the Rerofit library, you must configure its dependencies in build.gradle:
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.6.2'
}
In addition to the Rerofit library, a gson library is added in the above example. In fact, the gson library is optional. By default, Retrofit can only deserialize the HTTP response result to OkHttp's ResponseBody type and can only accept its RequsetBody type is @Body (described later). However, other converters can be added to support other types through the addConverterFactory method. You can support its serialization operation by adding the following dependency packages.
- Gson: com.squareup.retrofit2:converter-gson
- Jackson: com.squareup.retrofit2:converter-jackson
- Moshi: com.squareup.retrofit2:converter-moshi
- Protobuf: com.squareup.retrofit2:converter-protobuf
- Wire: com.squareup.retrofit2:converter-wire
- Simple XML: com.squareup.retrofit2:converter-simplexml
Of course, you can also create your own converter in a custom way, as long as you create a class that inherits from Converter.Factory and implement the responseBodyConverter and requestBodyConverter methods, and then use addConverterFactory to add an instance when adding the adapter.
3.2 Annotation of request method
From the AppInfoService in the above example, you will find that a @GET annotation is defined in the getAppInfoList method. In fact, a lot of Refit is completed by means of annotations. The method of HTTP request annotations 8 species, which are the GET , the POST , the PUT , the DELETE , the HEAD , the PATCH , the OPTIONS and HTTP . Among them, the first 7 types correspond to HTTP request methods; and the last type HTTP is a general annotation, which can be replaced by parameters. Use as:
@HTTP(method = "GET", path = " url.json", hasBody = false)
Call<List<AppInfo>> getAppInfoList();
method indicates the method of the request, note that it is case sensitive
path represents the network request address path
hasBody indicates whether there is a request body
3.3 Request header comments
There are two types of request header annotations: Headers and Header . The difference is that the former is generally used for the request header of the firmware, and multiple ones can be added; the latter is generally used for the non-fixed request header, which is used as the parameter input of the method, such as:
@Headers({"Accept: application/vnd.github.v3.full+json", "User-Agent: Retrofit-Sample-App"})
@GET("url.json")
Call<List<AppInfo>> getAppInfoList(@Header("Authorization") String authorization);
3.3 Parameter annotations
Parameter annotations include: Body , Path , Field , FieldMap , Part , PartMap , Query , QueryMap , Url, etc.
3.3.1 Body
Used to send HTTP request body for Post request, for example, GsonConverterFactory has been added, you can pass in the class object, use such as:
@POST("users/new")
Call<User> createUser(@Body User user);
3.3.2 Path
Used as a placeholder in Url, used as:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
3.3.3 Field 和 FieldMap
Used to pass parameters in the form of a form when used for Post requests, which needs to be used in conjunction with @FromUrlEncoded, such as:
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@FieldMap Map<String, String> map);
3.3.4 Part and PartMap
It is used to post parameters in the form of a form when used for Post requests. It is different from @Field. It can carry more abundant parameter types. For example, it can carry data streams when uploading files.
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
@Multipart
@PUT("user/photo")
Call<User> updateUser(@PartMap Map<String, RequestBody> map);
3.3.5 Query and QueryMap
Used to pass parameters when getting a request, use such as:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
3.3.6 Url
Used to specify the request path, such as:
@GET
Call<List<AppInfo>> getAppInfoList(@Url String url, @Query("id") int id);
3.4 Marker annotations
There are three kinds of annotations for markup: FormUrlEncoded , Multipart , Streaming .
3.4.1 FormUrlEncoded
When used for Post requests, when the requesting entity is a From form, each key-value pair needs to be annotated with @Field, so that Field and FieldMap are introduced as above.
3.4.2 Multipart
When used for Post requests, the request entity is rich in parameter types, such as data streams that can be carried when uploading files. Each key-value pair needs to be annotated with @Part, so that Part and PartMap are described above.
3.4.3 Streaming
Generally, when downloading a large file, you need to add @Streaming annotation, which means that the response is returned in the form of a byte stream, so that you can avoid all large files being loaded into memory.
3.5 Synchronous and asynchronous
Call objects can make network requests synchronously or asynchronously, and each object can only be used once. If you want to execute multiple times, you can call clone () to create a new object. It should also be noted that in Android, the callback will be executed in the main thread, while in the JVM, the callback will be in the same thread as the HTTP request.
Sample code for synchronous execution:
try {
Response<List<AppInfo>> response = call.execute();
List<AppInfo> appInfos = response.body();
Log.e("zyx", appInfos.toString());
} catch (IOException e) {
e.printStackTrace();
}
Sample code for asynchronous execution:
call.enqueue(new Callback<List<AppInfo>>() {
@Override
public void onResponse(Call<List<AppInfo>> call, Response<List<AppInfo>> response) {
List<AppInfo> appInfos = response.body();
Log.e("zyx", appInfos.toString());
}
@Override
public void onFailure(Call<List<AppInfo>> call, Throwable t) {
Log.e("zyx", t.toString());
}
});
After seeing the above synchronous and asynchronous code, do you have any familiar thanks? We previously learned that OkHttp's synchronous and asynchronous requests are similar codes, because the bottom of the Rerofit framework originally used OkHttp.