
本文共 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 ConverterresponseBodyConverter(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("/") //由于我们是解析首页,也就是根目录,所以这边写"/" Callbaidu();}
5,用Retrofit对象,通过动态代理创建网络请求接口的代理类;
HttpService service = retrofit.create(HttpService.class);
6,根据网络请求接口的代理对象,创建实际发起网络请求的Call对象
Callcall = 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、@URL1,网络请求方法
@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) { Mapparams = 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")CallworkPlanList(@Field("type") String type);
2.2,Multipart
每个键值对需要用请求参数@Part来注解键名,随后的对象是需要提供值。
@Multipart@POST("game/findgamebinsb")CallgameList(@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 CalltestFormUrlEncoded1(@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")CalldownloadFile(@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")CallgetUser(@Header("Authorization") String authorization)// @Headers@Headers("Authorization: authorization")@GET("user")Call getUser()// 以上的效果是一致的。
@Body
@POST("push/receive")CallpushCallBack(@Body RequestBody route);
@Field、@FieldMap
与@FormUrlEncoded注解配合使用
/** *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded) * @Field("username")表示将后面的 String name 中name的取值作为 username 的值 */ @POST("/form") @FormUrlEncoded CalltestFormUrlEncoded1(@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 CalltestFileUpload1(@Part("name") RequestBody name,@Part("age") RequestBody age, @Part MultipartBody.Part file);
@Query、@QueryMap
用于 @GET
方法的查询参数
@GET("game/getOneGame")CallgameDetail(@Query("gameid") String gameid);
@Path
URL地址的缺省值
注1:{占位符}和path尽量只用在URL的path部分,url中的参数使用@Query和@QueryMap 代替,保证接口定义的简洁
注2:@Query、@Field和@Part这三者都支持数组和实现了Iterable接口的类型,如List,Set等,方便向后台传递数组。@GET("users/{user}/repos") CallgetBlog(@Path("user") String user ); // 访问的API是:https://api.github.com/users/{user}/repos // 在发起请求时, {user} 会被替换为方法的第一个参数 user(被@Path注解作用)
@URL
直接传入一个请求的 URL变量 用于URL设置
@GETCalltestUrlAndQuery(@Url String url, @Query("isShow") boolean isShow);// 当有URL注解时,@GET传入的URL就可以省略// 当GET、POST...HTTP等方法中没有设置Url时,则必须使用 {@link Url}提供
发表评论
最新留言
关于作者
