一.概述
1.什么是retrofit
retrofit是现在比较流行的网络请求框架,可以理解为okhttp的加强版,底层封装了Okhttp。准确来说,Retrofit是一个RESTful的http网络请求框架的封装。因为网络请求工作本质上是由okhttp来完成,而Retrofit负责网络请求接口的封装。
本质过程:App应用程序通过Retrofit请求网络,实质上是使用Retrofit接口层封装请求参数、Header、Url等信息,之后由okhttp来完成后续的请求工作。在服务端返回数据后,okhttp将原始数据交给Retrofit,Retrofit根据用户需求解析。
2.优点
- 超级解耦 ,接口定义、接口参数、接口回调不在耦合在一起
- 可以配置不同的httpClient来实现网络请求,如okhttp、httpclient
- 支持同步、异步、Rxjava
- 可以配置不同反序列化工具类来解析不同的数据,如json、xml
- 请求速度快,使用方便灵活简洁
使用
先贴上官方网址 点击跳转…
-
添加Retrofit库的依赖
-
创建 接收服务器返回数据 的类
-
创建 用于描述网络请求 的接口
-
创建 Retrofit 实例
-
创建 网络请求接口实例 并 配置网络请求参数
-
发送网络请求(采用最常用的异步方式)
-
处理服务器返回的数据
1.添加Retrofit库的依赖
//Retrofit库
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
//使用gson解析要用到的
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
//添加 网络权限 AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
2.创建 接收服务器返回数据 的类
public class Info {
@SerializedName("code")
private int code;
private String message;
@SerializedName("data")
private Data data;
public class Data{
@SerializedName("name")
private String name;
@SerializedName("url")
private String url;
@SerializedName("picurl")
private String picurl;
public String getName() {
return name;
}
public String getUrl() {
return url;
}
public String getPicurl() {
return picurl;
}
}
public Data getData() {
return data;
}
}
3.创建 用于描述网络请求 的接口
public interface GetRequest_Interface {
//get请求
//有参方法
@GET("api/rand.music")
Call<Info> getJsonData(@Query("sort") String sort, @Query("format") String format);
//最后的部分uri相当与api/rand.music?sort=传入的参数&format=传入的参数
//无参
@GET("api/rand.music?sort=%E6%96%B0%E6%AD%8C%E6%A6%9C&format=json")
Call<Info> getJsonData1();
//post请求
@FormUrlEncoded
@POST("api/comments.163")
Call<Object> postDataCall(@Field("format") String format);
}
这里特别说明Url的组成,retrofit把网络请求的URl分成两部分设置:第一部分在创建Retrofit实例时通过.baseUrl()设置,这里的部分URI必须以/结尾
第二部分在网络接口注解中设置,如下面的"api/rand.music",网络请求的完整地址Url = Retrofit实例.baseUrl()+网络请求接口注解()
各种请求的使用方法
//get请求网络方法,需要在方法头部添加@GET注解,表示采用get方法访问网络请求,括号内的是请求的地址(Url的一部分)
//其中返回类型是Call<*>,*表示接收数据的类,如果想直接获取ResponseBody中的内容,可以定义网络请求返回值为Call<ResponseBody>,
//ResponseBody是请求网络后返回的原始数据,如果网络请求没有参数,不用写
@GET("user")
Call<ResponseBody> getData1();
//get请求网络方法,添加参数在方法括号内添加@Query,后面是参数类型和参数字段,其实就是键值对,Retrofit会把两个字段拼接到接口中
//表示后面idLon的取值作为"id"的值,nameStr的取值作为"name"的值
@GET("user")
Call<ResponseBody> getData2(@Query("id") long idLon, @Query("name") String nameStr);
//如果有多个不确定的参数可以使用@QueryMap注解,通过将参数传入Map中,再统一提交参数,类似多个Query
@GET("user")
Call<ResponseBody> getData3(@QueryMap Map<String, Object> map);
//post请求网络方法,需要在方法头部添加@POST注解,表示采用post方法访问网络请求
@POST("user/emails")
Call<ResponseBody> getPostData();
//如果有参数需要在头部添加@FormUrlEncoded注解,表示请求实体是一个From表单,每个键值对需要使用@File注解
//在方法括号内使用@Field添加参数,这是发送Post请求时,提交请求的表单字段,必须要添加的,而且需要配合@FormUrlEncoded使用
@FormUrlEncoded
@POST("user/emails")
Call<ResponseBody> getPostData2(@Field("name") String nameStr, @Field("sex") String sexStr);
//@FieldMap与@Field的作用一致,可以用于添加多个不确定的参数,类似@QueryMap,Map的key作为表单的键,Map的value作为表单的值
@FormUrlEncoded
@POST("user/emails")
Call<ResponseBody> getPostData3(@FieldMap Map<String, Object> map);
//@Body可以传递自定义类型数据给服务器,多用于post请求发送非表单数据,比如用传递Json格式数据,它可以注解很多东西,比如HashMap、实体类等
//特别注意:@Body注解不能用于表单或者支持文件上传的表单的编码,即不能与@FormUrlEncoded和@Multipart注解同时使用,否则会报错
@POST("user/emails")
Call<ResponseBody> getPsotDataBody(@Body RequestBody body);
//@HTTP注解是替换@GET、@POST、@PUT、@DELETE、@HEAD以及更多拓展功能
//method:表示请求的方法,区分大小写,这里的值retrofit不会再做任何处理,必须要保证正确
//path:网络请求地址路径
//hasBody:是否有请求体
@HTTP(method = "GET", path = "user/keys", hasBody = false)
Call<ResponseBody> getHttpData();
//@Path注解用于Url中的占位符{},所有在网址中的参数,如下面的id,通过{}占位符来标记id,通过使用@Path注解传入id的值
//注意有的Url既有占位符又有"?"后面的键值对,其实@Query和@Path两者是可以共用的
@GET("orgs/{id}")
Call<ResponseBody> getPathData(@Query("name") String nameStr, @Path("id") long idLon);
//@URL注解表示指定请求路径,如果需要重新地址接口地址,可以使用@URL,将地址以参数的形式传入即可。
//如果有@Url注解时,GET传入的Url可以省略
@GET
Call<ResponseBody> getUrlData(@Url String nameStr, @Query("id") long idLon);
//@Header添加固定的请求头
//作为方法的参数传入,用于添加不固定的header,该注解会更新已有的请求头
@GET("user/emails")
Call<ResponseBody> getHeaderData(@Header("token") String token);
//用于添加固定请求头,可以同时添加多个,通过该注解添加的请求头不会相互覆盖,而是共同存在
@Headers({"phone-type:android", "version:1.1.1"})
@GET("user/emails")
Call<ResponseBody> getHeadersData(@Header("token") String token);
//表示响应体的数据用流的方式返回,使用于返回数据比较大,该注解在下载大文件时特别有用
@Streaming
@POST("gists/public")
Call<ResponseBody> getStreamingBig();
//@Multipart表示请求实体是一个支持文件上传的表单,需要配合@Part和@PartMap使用,适用于文件上传
//@Part用于表单字段,适用于文件上传的情况,@PartMap用于表单字段,可用于多文件上传的情况
//@Part支持三种类型:RequestBody、MultipartBody.Part、任意类型
@Multipart
@POST("user/followers")
Call<ResponseBody> getPartData(@Part("name") RequestBody name, @Part MultipartBody.Part file);
@Multipart
@POST("user/followers")
Call<ResponseBody> getPartMapData(@PartMap Map<String, MultipartBody.Part> map);
4. 创建 Retrofit 实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.uomg.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
5. 创建 网络请求接口实例 并 配置网络请求参数
GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
//无参方法
// Call<Info> call = request.getJsonData1();
//带参方法
Call<Info> call = request.getJsonData("新歌榜","json");
6.发送网络请求(采用最常用的异步方式),处理返回的数据
//打印完整的uri
//Log.d("MainActivity","get == url:" + call.request().url());
call.enqueue(new retrofit2.Callback<Info>() {
@Override
public void onResponse(@NotNull Call<Info> call, @NotNull retrofit2.Response<Info> response) {
assert response.body() != null;
Log.d(TAG,"retrofit: "+response.body().getData().getName());
Log.d(TAG,"retrofit: "+response.body().getData().getPicurl());
Log.d(TAG,"retrofit: "+response.body().getData().getUrl());
}
@Override
public void onFailure(@NotNull Call<Info> call, @NotNull Throwable t) {
Toast.makeText(MainActivity.this, "连接错误", Toast.LENGTH_LONG).show();
}
});