当前位置: 首页 > 工具软件 > retrofit-cjs > 使用案例 >

Retrofit2的使用及注解分析

施海
2023-12-01

目录

Retrofit简介

Retrofit2使用

Retrofit注解介绍

请求参数注解


Retrofit简介

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

官网地址

https://github.com/square/retrofit

https://square.github.io/retrofit/#introduction

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,添加网络请求权限

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

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

Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://www.baidu.com")
                    .addConverterFactory(new Converter.Factory() {
                                @Override
                                public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
                                    //return super.responseBodyConverter(type, annotations, retrofit);
                                    return new Converter<ResponseBody, String>() {
                                        @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<String> baidu();
}

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

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

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

 Call<String> call = service.baidu();

7,发起网络请求

//异步请求
call.enqueue(new Callback<String>() {
                @Override
                public void onResponse(Call<String> call, Response<String> response) {
                    //处理网络请求返回的数据
                    System.out.println("测试Retrofit");
                    System.out.println(response.body());
                }

                @Override
                public void onFailure(Call<String> call, Throwable t) {

                }
            });

//同步请求
 Response<String> 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);

完整地址是 http://192.168.1.1:8080/b/c  不是原本的 http://192.168.1.1:8080/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<String, String> 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<ResponseBody> getBingImage(@QueryMap Map<String, String> params);

        @GET("HPImageArchive.aspx?")
        Call<ResponseBody> getBingImage(@QueryMap Map<String, String> 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<String,String> params) {
        Retrofit retrofit = new Retrofit.Builder().baseUrl("https://cn.bing.com/").build();
        BingImageUtil bingImageUtil = retrofit.create(BingImageUtil.class);

        Call<ResponseBody> call = bingImageUtil.getBingImage(params);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                try {
                    System.out.print("必应每日图片获取数据 " + response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {

            }
        });
    }

2,标记类型

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

2.1,@FormUrlEncoded

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

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

2.2,Multipart

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

@Multipart
@POST("game/findgamebinsb")
Call<ResponseBody> gameList(@PartMap Map<String, RequestBody> requestBodyMap);

@FormUrlEncoded注解和@Multipart注解案例

public interface HttpService_Interface {
        /**
         *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
         * @Field("username")表示将后面的 String name 中name的取值作为 username 的值
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);
         
        /**
         * @Part后面支持三种类型,RequestBody、 okhttp3.MultipartBody.Part 、任意类型
         * 除okhttp3.MultipartBody.Part以外,其它类型都必须带上表单字段(okhttp3.MultipartBody.Part中已经包含了表单字段的信息),
         */
        @POST("/form")
        @Multipart
        Call<ResponseBody> 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<ResponseBody> 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<ResponseBody> call2 = service.testFileUpload1(name,age, filePart);
    }

2.3,Streaming

@Streaming
@GET("/update_apk")
Call<ResponseBody> 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非表单请求体
@PathURL缺省值
@URLURL设置

详细说明

@Headers、@Header

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


// @Header
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

// @Headers
@Headers("Authorization: authorization")
@GET("user")
Call<User> getUser()

// 以上的效果是一致的。

@Body

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

@Field、@FieldMap

与@FormUrlEncoded注解配合使用

/**
         *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
         * @Field("username")表示将后面的 String name 中name的取值作为 username 的值
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> 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<ResponseBody> testFileUpload1(@Part("name") RequestBody name,@Part("age") RequestBody age, @Part MultipartBody.Part file);

@Query、@QueryMap

用于 @GET 方法的查询参数

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

@URL

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

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

 

 类似资料: