Retrofit2的使用及注解分析
发布日期:2021-05-10 13:30:51 浏览次数:24 分类:精选文章

本文共 9596 字,大约阅读时间需要 31 分钟。

目录


Retrofit简介

Retrofit是Square公司出品的网络请求封装库,注意是封装框架,不是网络请求框架;Retrofit底层网络请求是通过OKHttp实现的,Retrofit只是在此基础上做了很好的封装,使其更好用,更方便,更强大,而且能很多开源库(比如:GSON,Rxjava)配合使用;把网络请求通过注解封装成一个接口;

官网地址

Retrofit2使用

网络请求是获取百度搜索页的数据

1,引入Retrofit2依赖,由于Retorift2已经内置了OKHttp所以不需要额外引入OkHttp了;

implementation 'com.squareup.retrofit2:retrofit:2.6.2'//Retorift2依赖implementation 'com.squareup.retrofit2:converter-gson:2.6.2'//数据解析转换器implementation 'com.squareup.retrofit2:adapter-rxjava:2.6.2'//支持RxJava

注意:后面两个依赖可以不加, 如果不加拿到网络请求原始数据(例如接口返回的原始数据)之后自己做解析转换,或者和RxJava对接;也可以加上,这样就不用自己解析数据,可以通过添加的数据转换器转换自己所需的数据类型(例如 Observable<Java Bean>)或Java Bean;

2,添加网络请求权限

3,创建Retrofit实例,baseUrl方法参数不可以为空;必须以http或者https开头; 必须以 /(斜线) 结束,代表根路径;但是有隐含的 / 就不需要了;

Retrofit retrofit = new Retrofit.Builder()                    .baseUrl("http://www.baidu.com")                    .addConverterFactory(new Converter.Factory() {                                @Override                                public Converter
responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { //return super.responseBodyConverter(type, annotations, retrofit); return new Converter
() { @Override public String convert(ResponseBody value) throws IOException { //return null; return value.string(); } }; } } ) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build();

4,创建网络请求Java接,一个接口可以定义多个网络请求方法;Retrofit采用注解描述网络请求参数和配置网络请求参数,有关Retrofit的注解参数的使用下面单独接受;

public interface HttpService {    @GET("/")  //由于我们是解析首页,也就是根目录,所以这边写"/"    Call
baidu();}

5,用Retrofit对象,通过动态代理创建网络请求接口的代理类;

HttpService service = retrofit.create(HttpService.class);

6,根据网络请求接口的代理对象,创建实际发起网络请求的Call对象

Call
call = service.baidu();

7,发起网络请求

//异步请求call.enqueue(new Callback
() { @Override public void onResponse(Call
call, Response
response) { //处理网络请求返回的数据 System.out.println("测试Retrofit"); System.out.println(response.body()); } @Override public void onFailure(Call
call, Throwable t) { } });//同步请求 Response
response = call.execute();//处理网络请求返回的数据 System.out.println(response.body()); //esponse.body()就是String对象

注意:网络请求的完整Url = 在创建Retrofit实例时通过.baseUrl()设置的 + 网络请求接口的注解设置(下面称 “path

path = "/a/b"是绝对路径 

path="a/b"是先对路径;

path是绝对路径时,会覆盖baseUrl除Ip和端口以外的路径;

Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://192.168.1.1:8080/aa/").build();

 
@POST("/b/c")
Call<ResponseBody> login(@Body RequestBody requestBody);

完整地址是 b/c  不是原本的 aa/b/c

Retrofit注解介绍

总共22个注解,根据功能大概分为三类:

请求方法类型

@GET、@POST、@PUT、@DELETE、@PATCH、@HEAD、@OPTIONS、@HTTP

标记类型

@FormUrlEncoded、@Multipart、@Streaming

参数类型

@Headers、@Header、@Body、@Field、@FieldMap、@Part、@PartMap、@Query、@QueryMap、@Path、@URL

1,网络请求方法

@GET、@POST、@PUT、@DELETE、@PATCH、@HEAD、@OPTIONS、@HTTP和Http网络请求方法(GET,POST,PUT...等请求方法)一一对应;

Http请求方法 Retrofit注解名称 关系
GET @GET 所有注解分别对应Http网络请求中的方法,都接收网络地址Url
POST @POST
PUT @PUT
DELETE @DELETE
PATCH @PATCH
HEAD @HEAD
OPTIONS @OPTIONS
  @HTTP 用来替换以上其中注解,可以扩展其功能

例如:通过GET方法获取必应每日图片的数据

URL完整路径:https://cn.bing.com/HPImageArchive.aspx?format=js&idx=1&n=1&nc=1498657985239&pid=hp&video=1

public static void main(String[] args) {        Map
params = new HashMap<>(); params.put("format", "js"); params.put("idx", "1"); params.put("n", "1"); params.put("pid", "1498657985239"); params.put("nc", "hp"); params.put("video", "1"); getBingDate(params); } public interface BingImageUtil { //通过HTTP注解替换GET /** * method:网络请求的方法(区分大小写) * path:网络请求地址路径 * hasBody:是否有请求体 */// @HTTP(method = "GET", path = "HPImageArchive.aspx?", hasBody = false)// Call
getBingImage(@QueryMap Map
params); @GET("HPImageArchive.aspx?") Call
getBingImage(@QueryMap Map
params); } //URL全路径:https://cn.bing.com/HPImageArchive.aspx?format=js&idx=1&n=1&nc=1498657985239&pid=hp&video=1 public static void getBingDate(Map
params) { Retrofit retrofit = new Retrofit.Builder().baseUrl("https://cn.bing.com/").build(); BingImageUtil bingImageUtil = retrofit.create(BingImageUtil.class); Call
call = bingImageUtil.getBingImage(params); call.enqueue(new Callback
() { @Override public void onResponse(Call
call, Response
response) { try { System.out.print("必应每日图片获取数据 " + response.body().string()); } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(Call
call, Throwable t) { } }); }

2,标记类型

Retrofit注解名称 释义 使用位置
@FormUrlEncoded 表示请求体是一个From表单 网络请求接口的方法上
@Multipart 表示请求体是一个支持文件上传的Form表单
@Streaming 表示请求的数据以流的形式返回;未使用该注解,默认会把数据全部载入内存,之后通过流获取数据也是读取内存中数据,所以返回数据较大时,需要使用该注解,不然会产生OOM

2.1,@FormUrlEncoded

每个键值对需要用请求参数@Filed来注解键名,随后的对象是需要提供的值。

@FormUrlEncoded@POST("/form")Call 
workPlanList(@Field("type") String type);

2.2,Multipart

每个键值对需要用请求参数@Part来注解键名,随后的对象是需要提供值。

@Multipart@POST("game/findgamebinsb")Call
gameList(@PartMap Map
requestBodyMap);

@FormUrlEncoded注解和@Multipart注解案例

public interface HttpService_Interface {        /**         *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)         * @Field("username")表示将后面的 String name 中name的取值作为 username 的值         */        @POST("/form")        @FormUrlEncoded        Call
testFormUrlEncoded1(@Field("username") String name, @Field("age") int age); /** * @Part后面支持三种类型,RequestBody、 okhttp3.MultipartBody.Part 、任意类型 * 除okhttp3.MultipartBody.Part以外,其它类型都必须带上表单字段(okhttp3.MultipartBody.Part中已经包含了表单字段的信息), */ @POST("/form") @Multipart Call
testFileUpload1(@Part("name") RequestBody name,@Part("age") RequestBody age, @Part MultipartBody.Part file);//使用 private void test() { HttpService_Interface service = retrofit.create(HttpService_Interface.class); // @FormUrlEncoded Call
call1 = service.testFormUrlEncoded1("Carson", 24); // @Multipart// RequestBody name = RequestBody.create(textType, "lza"); RequestBody name = RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), "lza"); RequestBody age = RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), "26"); File file = new File("fileUrl"); //上传一个文件 // 创建 RequestBody,用于封装构建RequestBody // RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file); RequestBody requestFile = RequestBody.create(MediaType.parse("image/jpg"), file); MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt",requestFile); Call
call2 = service.testFileUpload1(name,age, filePart); }

2.3,Streaming

@Streaming@GET("/update_apk")Call
downloadFile(@Url String fileUrl);

请求参数注解

@Headers、@Header、@Body、@Field、@FieldMap、@Part、@PartMap、@Query、@QueryMap、@Path、@URL

注解名称 作用 使用位置
@Headers 用于添加请求头 请求接口的方法上
@Header 添加不固定值的Header 请求接口的方法参数中
@Field 向Post表单中传键值对,与@FormUrlEncoded注解配合使用
@FieldMap
@Part 表单字段,与@Multipart注解配合使用,适合有文件上传的情况
@PartMap
@Query 用于表单字段,作用和@Field@FieldMap相同;区别:@Query和@QueryMap中的数据体现在Url上,而@Field和@FieldMap的数据是请求体,但最后生成的数据形式是一样的
@QueryMap
@Body 非表单请求体
@Path URL缺省值
@URL URL设置

详细说明

@Headers、@Header

区别在于使用场景和使用方式 :1, 使用场景:@Header用于添加不固定的请求头,@Headers用于添加固定的请求头 2, 使用方式:@Header作用于方法的参数;@Headers作用于方法

// @Header@GET("user")Call
getUser(@Header("Authorization") String authorization)// @Headers@Headers("Authorization: authorization")@GET("user")Call
getUser()// 以上的效果是一致的。

@Body

@POST("push/receive")Call
pushCallBack(@Body RequestBody route);

@Field、@FieldMap

与@FormUrlEncoded注解配合使用

/**         *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)         * @Field("username")表示将后面的 String name 中name的取值作为 username 的值         */        @POST("/form")        @FormUrlEncoded        Call
testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);

@Part、@PartMap

与@Multipart注解配合使用

/**         * @Part后面支持三种类型,RequestBody、 okhttp3.MultipartBody.Part 、任意类型         * 除okhttp3.MultipartBody.Part以外,其它类型都必须带上表单字段(okhttp3.MultipartBody.Part中已经包含了表单字段的信息),         */        @POST("/form")        @Multipart        Call
testFileUpload1(@Part("name") RequestBody name,@Part("age") RequestBody age, @Part MultipartBody.Part file);

@Query、@QueryMap

用于 @GET 方法的查询参数

@GET("game/getOneGame")Call
gameDetail(@Query("gameid") String gameid);

@Path

URL地址的缺省值 

注1:{占位符}和path尽量只用在URL的path部分,url中的参数使用@Query和@QueryMap 代替,保证接口定义的简洁

注2:@Query、@Field和@Part这三者都支持数组和实现了Iterable接口的类型,如List,Set等,方便向后台传递数组。

@GET("users/{user}/repos") Call
getBlog(@Path("user") String user ); // 访问的API是:https://api.github.com/users/{user}/repos // 在发起请求时, {user} 会被替换为方法的第一个参数 user(被@Path注解作用)

@URL

直接传入一个请求的 URL变量 用于URL设置

@GETCall
testUrlAndQuery(@Url String url, @Query("isShow") boolean isShow);// 当有URL注解时,@GET传入的URL就可以省略// 当GET、POST...HTTP等方法中没有设置Url时,则必须使用 {@link Url}提供

 

上一篇:Groovy配置环境和编译运行的几种方式
下一篇:Java 中的多态详解

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2025年04月08日 21时40分38秒