Use of Retrofit2 framework for Android network programming (11)

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.

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.

  1. Gson: com.squareup.retrofit2:converter-gson
  2. Jackson: com.squareup.retrofit2:converter-jackson
  3. Moshi: com.squareup.retrofit2:converter-moshi
  4. Protobuf: com.squareup.retrofit2:converter-protobuf
  5. Wire: com.squareup.retrofit2:converter-wire
  6. 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.

 

Published 106 original articles · praised 37 · 80,000 views

Guess you like

Origin blog.csdn.net/lyz_zyx/article/details/103367795