在Android应用中使用Retrofit 2

在Android应用中使用Retrofit 2


Retrofit是Android开发人员中用于联网的库,有些人甚至认为它在某种程度上是一种标准。 如此受欢迎的原因有很多:该库完全支持REST API,易于测试和配置,并且在其帮助下通过网络进行的请求非常简单。 在本文中,我将向您展示如何配置和使用Retrofit来实现与应用程序的联网。


配置改造


将以下依赖项添加到build.gradle文件:


 implementation 'com.squareup.retrofit2:retrofit:2.4.0' 

我们将使用Gson将JSON转换为POJO。 Retrofit提供了一个依赖项,可以自动将JSON转换为POJO。 为此,向build.gradle文件添加另一个依赖build.gradle


 implementation 'com.squareup.retrofit2:converter-gson:2.3.0' 

如果尚未允许您的应用程序与网络一起使用,请确保将相应的行添加到AndroidManifest文件中:


 <uses-permission android:name="android.permission.INTERNET"/> 

添加依赖项后,我们需要编写代码来配置Retrofit库。


创建一个名为NetworkService的类:


 public class NetworkService { } 

该类必须是一个单例对象,因此声明一个静态变量和一个函数,该函数创建并返回与该类相同类型的变量。 如果您不知道此模式如何工作,请查看本文 ,其中包含Java语言的实现示例。


 public class NetworkService { private static NetworkService mInstance; public static NetworkService getInstance() { if (mInstance == null) { mInstance = new NetworkService(); } return mInstance; } } 

为了进行测试,我们使用JSONPlaceholder ,它为开发人员提供了伪造的在线REST API:


 https://jsonplaceholder.typicode.com 

现在,我们将在NetworkService构造函数中声明和初始化Retrofit:


 public class NetworkService { private static NetworkService mInstance; private static final String BASE_URL = "https://jsonplaceholder.typicode.com"; private Retrofit mRetrofit; private NetworkService() { mRetrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } public static NetworkService getInstance() { if (mInstance == null) { mInstance = new NetworkService(); } return mInstance; } } 

配置完成,现在我们需要确定将返回数据的端点


添加端点


创建一个名为JSONPlaceHolderApi的接口:


 public interface JSONPlaceHolderApi { } 

JSONPlaceHolder站点上 URL /posts/id是返回具有适当标识符的消息的端点。 该端点接收GET请求,并以JSON格式返回数据,如下所示:


 { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" } 

首先,我们将为JSON响应创建适当的POJO:


 public class Post { @SerializedName("userId") @Expose private int userId; @SerializedName("id") @Expose private int id; @SerializedName("title") @Expose private String title; @SerializedName("body") @Expose private String body; public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } } 

如您所见,这是一个简单的POJO类。 我们使用@SerializedName()注释了变量,并在其中传递了名称。 这些名称实际上是从API返回的JSON数据中的键,因此您可以根据需要更改变量名称,但请确保传递给@SerializedName()批注的名称@SerializedName()存在于JSON中。


在上面创建的接口中,使用必需的参数定义端点:


 public interface JSONPlaceHolderApi { @GET("/posts/{id}") public Call<Post> getPostWithID(@Path("id") int id); } 

由于我们正在发送GET请求,因此我们需要对方法应用@GET批注,该方法在其中是要向其发送请求的端点。 如您所见,我们没有添加完整的URL,因为 Retrofit将自动采用传递给NetworkService类的BASE_URL并将其添加到URL的其余部分。


该方法的返回类型称为Call<Post>Call是由库本身直接提供的类。 接口中的所有方法都应返回此类型的值。 这是一个通用类,它接受我们要转换为JSON的对象的类型。 我们通过了Post因为 这正是我们要将JSON响应转换为的对象。 我们将一个整数传递给参数,并使用@Path对其进行注释,并在其中编写了id 。 改造将采用此值,并且在端点处将{id}替换为该值。 因此,如果我们传递值1作为参数,则端点将看起来像是/posts/1 ,如果传递值10,则端点将是/posts/10


现在,我们需要Retrofit以提供JSONPlaceHolderApi接口的实现。 为此,请使用create()方法:


 public class NetworkService { private static NetworkService mInstance; private static final String BASE_URL = "https://jsonplaceholder.typicode.com"; private Retrofit mRetrofit; private NetworkService() { mRetrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } public static NetworkService getInstance() { if (mInstance == null) { mInstance = new NetworkService(); } return mInstance; } public JSONPlaceHolderApi getJSONApi() { return mRetrofit.create(JSONPlaceHolderApi.class); } } 

接下来,您需要从NetworkService获取JSONPlaceHolderApi并发送请求:


 NetworkService.getInstance() .getJSONApi() .getPostWithID(1) .enqueue(new Callback<Post>() { @Override public void onResponse(@NonNull Call<Post> call, @NonNull Response<Post> response) { Post post = response.body(); textView.append(post.getId() + "\n"); textView.append(post.getUserId() + "\n"); textView.append(post.getTitle() + "\n"); textView.append(post.getBody() + "\n"); } @Override public void onFailure(@NonNull Call<Post> call, @NonNull Throwable t) { textView.append("Error occurred while getting request!"); t.printStackTrace(); } }); 

返回的Call对象包含一个名为enqueue的方法,该方法将Callback<T>作为参数。 在onResponse我们获得包含服务器返回的Post对象的Response<Post>结果。 为了获取Post对象本身,我们使用response.body()方法。 其余代码无需进一步解释即可理解。


发送不同类型的请求


JSONPlaceHolder API具有许多可以使用的端点。


获取消息列表


 @GET("/posts") public Call<List<Post>> getAllPosts(); 

为了获得所有消息的列表,我们更改了端点并返回了函数的类型。


发送带有参数的请求


如果要发送带有参数的请求, @Query()需要在方法中的相应参数上使用@Query()批注:


 @GET("/posts") public Call<List<Post>> getPostOfUser(@Query("userId") int id); 

因此,如果我们在method参数中传递值6,则端点将为/posts?userId=6


发送POST请求


要发送POST请求,您只需要更改方法的注释即可。


 @POST("/posts") public Call<Post> postData(@Body Post data); 

为了形成此方法的请求主体,我们对传递的参数使用@Body批注。 Retrofit将使用Gson将@Body转换为JSON。


您可以使用多种其他类型的查询,但这是另一篇文章的主题。


请求拦截


改造提供了一种拦截请求并将其记录到Logcat中的方法。 让我们设置一个拦截器,看看这个魔术。 将以下依赖项添加到build.gradle文件:


 implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0' 

通过以下方式更新NetworkService类:


 public class NetworkService { private static NetworkService mInstance; private static final String BASE_URL = "https://jsonplaceholder.typicode.com"; private Retrofit mRetrofit; private NetworkService() { HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder client = new OkHttpClient.Builder() .addInterceptor(interceptor); mRetrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .client(client.build()) .build(); } public static NetworkService getInstance() { if (mInstance == null) { mInstance = new NetworkService(); } return mInstance; } public JSONPlaceHolderApi getJSONApi() { return mRetrofit.create(JSONPlaceHolderApi.class); } } 

现在,当您发送或接收请求时,其所有数据(包括URL,标头,正文)将显示在日志中:


 D/OkHttp: <-- 200 https://jsonplaceholder.typicode.com/posts/1 (3030ms) date: Tue, 24 Apr 2018 15:25:19 GMT content-type: application/json; charset=utf-8 set-cookie: __cfduid=d16d4221ddfba20b5464e6829eed4e3d11524583519; expires=Wed, 24-Apr-19 15:25:19 GMT; path=/; domain=.typicode.com; HttpOnly x-powered-by: Express vary: Origin, Accept-Encoding access-control-allow-credentials: true cache-control: public, max-age=14400 pragma: no-cache expires: Tue, 24 Apr 2018 19:25:19 GMT 04-24 15:25:16.204 7023-7056/com.thetehnocafe.gurleensethi.retrofitexample D/OkHttp: x-content-type-options: nosniff etag: W/"124-yiKdLzqO5gfBrJFrcdJ8Yq0LGnU" via: 1.1 vegur cf-cache-status: HIT expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" server: cloudflare cf-ray: 410994f328963066-SIN 04-24 15:25:16.246 7023-7056/com.thetehnocafe.gurleensethi.retrofitexample D/OkHttp: { 04-24 15:25:16.247 7023-7056/com.thetehnocafe.gurleensethi.retrofitexample D/OkHttp: "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" } <-- END HTTP (292-byte body) 

到此结束我们的文章。 您可以在GitHub上找到该项目的代码。

Source: https://habr.com/ru/post/zh-CN429058/


All Articles