改造安卓系统实例教程

今天,我们将使用 Square 开发的 **Retrofit ** 库来处理 Android 应用中的 REST API 调用。

安卓的回归

Retrofit 是针对 Android 和 Java 的类型安全的 REST 客户端,旨在使 RESTful 网页服务更容易使用。我们不会进入 Retrofit 1.x 版本的细节,然后直接跳到 Retrofit 2,它有许多新功能和与之前的版本相比的内部 API 更改。Retrofit 2 通过默认杠杆 **OkHttp**作为网络层,并建立在上面。

1compile 'com.squareup.retrofit2:retrofit:2.1.0'
2compile 'com.google.code.gson:gson:2.6.2'
3compile 'com.squareup.retrofit2:converter-gson:2.1.0'

OkHttp 依赖已与 Retrofit 2 依赖一起交付. 如果您希望使用单独的 OkHttp 依赖,则应将 OkHttp 依赖从 Retrofit 2 中排除为:

1compile ('com.squareup.retrofit2:retrofit:2.1.0') {  
2  // exclude Retrofit’s OkHttp dependency module and define your own module import
3  exclude module: 'okhttp'
4}
5compile 'com.google.code.gson:gson:2.6.2'
6compile 'com.squareup.retrofit2:converter-gson:2.1.0'
7compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
8compile 'com.squareup.okhttp3:okhttps:3.4.1'
  • Logging-interceptor 会生成返回的全部响应的日志字符串
  • 还有其他转换器可以将 JSON 解析到所需类型。
  1. Jackson : com.squareup.retrofit2:converter-jackson:2.1.0
  2. Moshi : com.squareup.retrofit2:converter-moshi:2.1.0
  3. Protobuf : com.squareup.retrofit2:converter-protobuf:2.1.0
  4. Wire : com.squareup.retrofit2:converter-wire:2.1.0
  5. 简单的XML : com.squareup.retrofit2:converter-simplex:2.1.0

在 AndroidManifest.xml 文件中添加访问互联网的权限。

OkHttp 拦截器

接收器是 OkHttp 中存在的强大的机制,可以监控、重写和重新调用呼叫,接收器主要可以分为两类:

  • 应用程序拦截器 : 要注册应用程序拦截器,我们需要在OkHttpClient.Builder 上呼叫addInterceptor() 网络拦截器 : 要注册网络拦截器,请呼叫addNetworkInterceptor()而不是addInterceptor()

设置 Retrofit 接口

 1package com.journaldev.retrofitintro;
 2
 3import com.journaldev.retrofitintro.pojo.MultipleResource;
 4
 5import okhttp3.OkHttpClient;
 6import okhttp3.logging.HttpLoggingInterceptor;
 7import retrofit2.Retrofit;
 8import retrofit2.converter.gson.GsonConverterFactory;
 9
10class APIClient {
11
12    private static Retrofit retrofit = null;
13
14    static Retrofit getClient() {
15
16        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
17        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
18        OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
19
20        retrofit = new Retrofit.Builder()
21                .baseUrl("https://reqres.in")
22                .addConverterFactory(GsonConverterFactory.create())
23                .client(client)
24                .build();
25
26        return retrofit;
27    }
28
29}

上面的代码中的getClient()方法在设置Retrofit接口时都会被调用。Retrofit为每个HTTP方法提供了注释列表:@GET, @POST, @PUT, @DELETE, @PATCH或 @HEAD

 1package com.journaldev.retrofitintro;
 2
 3import com.journaldev.retrofitintro.pojo.MultipleResource;
 4import com.journaldev.retrofitintro.pojo.User;
 5import com.journaldev.retrofitintro.pojo.UserList;
 6
 7import retrofit2.Call;
 8import retrofit2.http.Body;
 9import retrofit2.http.Field;
10import retrofit2.http.FormUrlEncoded;
11import retrofit2.http.GET;
12import retrofit2.http.POST;
13import retrofit2.http.Query;
14
15interface APIInterface {
16
17    @GET("/api/unknown")
18    Call<MultipleResource> doGetListResources();
19
20    @POST("/api/users")
21    Call<User> createUser(@Body User user);
22
23    @GET("/api/users?")
24    Call<UserList> doGetUserList(@Query("page") String page);
25
26    @FormUrlEncoded
27    @POST("/api/users?")
28    Call<UserList> doCreateUserWithField(@Field("name") String name, @Field("job") String job);
29}

在上面的类中,我们已经定义了一些执行HTTP请求与注释的方法。 @GET("/api/unknown")呼叫 doGetListResources();. doGetListResources()是方法的名称. MultipleResource.java是我们响应对象的模型POJO类别,用于将响应参数绘制到各自的变量。

 1package com.journaldev.retrofitintro.pojo;
 2
 3import com.google.gson.annotations.SerializedName;
 4
 5import java.util.ArrayList;
 6import java.util.List;
 7
 8public class MultipleResource {
 9
10    @SerializedName("page")
11    public Integer page;
12    @SerializedName("per_page")
13    public Integer perPage;
14    @SerializedName("total")
15    public Integer total;
16    @SerializedName("total_pages")
17    public Integer totalPages;
18    @SerializedName("data")
19    public List<Datum> data = null;
20
21    public class Datum {
22
23        @SerializedName("id")
24        public Integer id;
25        @SerializedName("name")
26        public String name;
27        @SerializedName("year")
28        public Integer year;
29        @SerializedName("pantone_value")
30        public String pantoneValue;
31
32    }
33}

@SerializedName annotation is used to specify the name of the field that's in the JSON Response. retrofit android example tutorial json schema Preview the POJO class and copy it into your Android Studio Project Structure. The POJO classes are wrapped into a typed Retrofit Call class. Note: A JSONArray is serialised a List of Objects in the POJO classes Method Parameters : There are a wide variety of possible options of parameters to pass inside a method:

  • @Body - 将 Java 对象发送为请求体
  • @Url - 使用动态 URL
  • @Query - 我们可以简单地添加 @Query 和查询参数名称的方法参数,描述类型。 若要使用 URL 编码查询,请使用表单: @Query(值 = "auth_token",编码 = true) String auth_token
  • @Field - 以 urlencoded 形式发送数据。

** 注意**: @Field 需要强制参数. 如果 @Field 是可选的,我们可以使用 @Query 代替并传递一个 null 值。

Retrofit Android 示例项目结构

android retrofit example tutorial, retrofit 2 tutorial The pojo package defines four model classes for each of the API endpoint responses defined in the APIInterface.java class. User.java

 1package com.journaldev.retrofitintro.pojo;
 2
 3import com.google.gson.annotations.SerializedName;
 4
 5public class User {
 6
 7    @SerializedName("name")
 8    public String name;
 9    @SerializedName("job")
10    public String job;
11    @SerializedName("id")
12    public String id;
13    @SerializedName("createdAt")
14    public String createdAt;
15
16    public User(String name, String job) {
17        this.name = name;
18        this.job = job;
19    }
20
21}

上面的类用于创建createUser()方法UserList.java的响应体。

 1package com.journaldev.retrofitintro.pojo;
 2
 3import com.google.gson.annotations.SerializedName;
 4
 5import java.util.ArrayList;
 6import java.util.List;
 7
 8public class UserList {
 9
10    @SerializedName("page")
11    public Integer page;
12    @SerializedName("per_page")
13    public Integer perPage;
14    @SerializedName("total")
15    public Integer total;
16    @SerializedName("total_pages")
17    public Integer totalPages;
18    @SerializedName("data")
19    public List<Datum> data = new ArrayList();
20
21    public class Datum {
22
23        @SerializedName("id")
24        public Integer id;
25        @SerializedName("first_name")
26        public String first_name;
27        @SerializedName("last_name")
28        public String last_name;
29        @SerializedName("avatar")
30        public String avatar;
31
32    }
33}

创建用户响应.java

 1package com.journaldev.retrofitintro.pojo;
 2
 3import com.google.gson.annotations.SerializedName;
 4
 5public class CreateUserResponse {
 6
 7    @SerializedName("name")
 8    public String name;
 9    @SerializedName("job")
10    public String job;
11    @SerializedName("id")
12    public String id;
13    @SerializedName("createdAt")
14    public String createdAt;
15}

MainActivity.java是我们在界面类中定义的每个 API 终端点的呼叫,并在 Toast/TextView 中显示每个字段。

  1package com.journaldev.retrofitintro;
  2
  3import android.support.v7.app.AppCompatActivity;
  4import android.os.Bundle;
  5import android.util.Log;
  6import android.widget.TextView;
  7import android.widget.Toast;
  8
  9import com.journaldev.retrofitintro.pojo.CreateUserResponse;
 10import com.journaldev.retrofitintro.pojo.MultipleResource;
 11import com.journaldev.retrofitintro.pojo.User;
 12import com.journaldev.retrofitintro.pojo.UserList;
 13
 14import java.util.List;
 15
 16import retrofit2.Call;
 17import retrofit2.Callback;
 18import retrofit2.Response;
 19
 20public class MainActivity extends AppCompatActivity {
 21
 22    TextView responseText;
 23    APIInterface apiInterface;
 24
 25    @Override
 26    protected void onCreate(Bundle savedInstanceState) {
 27        super.onCreate(savedInstanceState);
 28        setContentView(R.layout.activity_main);
 29        responseText = (TextView) findViewById(R.id.responseText);
 30        apiInterface = APIClient.getClient().create(APIInterface.class);
 31
 32        /**
 33         GET List Resources
 34         **/
 35        Call<MultipleResource> call = apiInterface.doGetListResources();
 36        call.enqueue(new Callback<MultipleResource>() {
 37            @Override
 38            public void onResponse(Call<MultipleResource> call, Response<MultipleResource> response) {
 39
 40                Log.d("TAG",response.code()+"");
 41
 42                String displayResponse = "";
 43
 44                MultipleResource resource = response.body();
 45                Integer text = resource.page;
 46                Integer total = resource.total;
 47                Integer totalPages = resource.totalPages;
 48                List<MultipleResource.Datum> datumList = resource.data;
 49
 50                displayResponse += text + " Page\n" + total + " Total\n" + totalPages + " Total Pages\n";
 51
 52                for (MultipleResource.Datum datum : datumList) {
 53                    displayResponse += datum.id + " " + datum.name + " " + datum.pantoneValue + " " + datum.year + "\n";
 54                }
 55
 56                responseText.setText(displayResponse);
 57
 58            }
 59
 60            @Override
 61            public void onFailure(Call<MultipleResource> call, Throwable t) {
 62                call.cancel();
 63            }
 64        });
 65
 66        /**
 67         Create new user
 68         **/
 69        User user = new User("morpheus", "leader");
 70        Call<User> call1 = apiInterface.createUser(user);
 71        call1.enqueue(new Callback<User>() {
 72            @Override
 73            public void onResponse(Call<User> call, Response<User> response) {
 74                User user1 = response.body();
 75
 76                Toast.makeText(getApplicationContext(), user1.name + " " + user1.job + " " + user1.id + " " + user1.createdAt, Toast.LENGTH_SHORT).show();
 77
 78            }
 79
 80            @Override
 81            public void onFailure(Call<User> call, Throwable t) {
 82                call.cancel();
 83            }
 84        });
 85
 86        /**
 87         GET List Users
 88         **/
 89        Call<UserList> call2 = apiInterface.doGetUserList("2");
 90        call2.enqueue(new Callback<UserList>() {
 91            @Override
 92            public void onResponse(Call<UserList> call, Response<UserList> response) {
 93
 94                UserList userList = response.body();
 95                Integer text = userList.page;
 96                Integer total = userList.total;
 97                Integer totalPages = userList.totalPages;
 98                List<UserList.Datum> datumList = userList.data;
 99                Toast.makeText(getApplicationContext(), text + " page\n" + total + " total\n" + totalPages + " totalPages\n", Toast.LENGTH_SHORT).show();
100
101                for (UserList.Datum datum : datumList) {
102                    Toast.makeText(getApplicationContext(), "id : " + datum.id + " name: " + datum.first_name + " " + datum.last_name + " avatar: " + datum.avatar, Toast.LENGTH_SHORT).show();
103                }
104
105            }
106
107            @Override
108            public void onFailure(Call<UserList> call, Throwable t) {
109                call.cancel();
110            }
111        });
112
113        /**
114         POST name and job Url encoded.
115         **/
116        Call<UserList> call3 = apiInterface.doCreateUserWithField("morpheus","leader");
117        call3.enqueue(new Callback<UserList>() {
118            @Override
119            public void onResponse(Call<UserList> call, Response<UserList> response) {
120                UserList userList = response.body();
121                Integer text = userList.page;
122                Integer total = userList.total;
123                Integer totalPages = userList.totalPages;
124                List<UserList.Datum> datumList = userList.data;
125                Toast.makeText(getApplicationContext(), text + " page\n" + total + " total\n" + totalPages + " totalPages\n", Toast.LENGTH_SHORT).show();
126
127                for (UserList.Datum datum : datumList) {
128                    Toast.makeText(getApplicationContext(), "id : " + datum.id + " name: " + datum.first_name + " " + datum.last_name + " avatar: " + datum.avatar, Toast.LENGTH_SHORT).show();
129                }
130
131            }
132
133            @Override
134            public void onFailure(Call<UserList> call, Throwable t) {
135                call.cancel();
136            }
137        });
138
139    }
140}

「apiInterface = APIClient.getClient().create(APIInterface.class);」用于实时化APIClient。 为了将模型类对我们所使用的响应进行映射:「MultipleResource resource = response.body();」运行应用程序将调用每个终端点并显示一个 Toast消息。 这将结束Retrofit android示例教程。 您可以从下面的链接下载Android Retrofit示例项目。

下载Retrofit Android示例项目

Published At
Categories with 技术
Tagged with
comments powered by Disqus