Retrofit在Android中使用
一、介绍
Retrofit 是一个 RESTful(一种架构风格)的 HTTP 网络请求框架的封装。注意这里并没有说它是网络请求框架,主要原因在于网络请求的工作并不是Retrofit 来完成的。Retrofit2.0 内置 OkHttp,Retrofit 得益于 OkHttp 的优势,较之于 Volley 是一种更加先进的网络框架。
Retrofit 专注于接口的封装,OkHttp 专注于网络请求的高效,二者分工协作!
我们的应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求参数、Header、Url 等信息,之后由 OkHttp 完成后续的请求操作,在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit,Retrofit 根据用户的需求对结果进行解析的过程。
二、使用步骤
1.添加Retrofit库的依赖:
implementation 'com.squareup.retrofit2:retrofit:2.0.2'
implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
后面三个是可选的,分别是数据解析器和gson,以及rxjava支持的依赖
2.创建 用于描述网络请求 的接口
Retrofit将 Http请求 抽象成 Java接口:采用 注解 描述网络请求参数 和配置网络请求参数
/**
* @Description: 用户信息
* @Author: dzh
* @CreateDate: 2019/4/25 20:54
*/
public interface TestService {
//获取测试接口信息
@GET()
Observable<Result<List<PublicEngModel>>> getNetData(@Url String url, @Header("checkCookie") boolean checkCookie);
}
3.创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://test.com/") //设置网络请求的Url地址
.addConverterFactory(GsonConverterFactory.create()) //设置数据解析器
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
4.添加调用的API层
/**
* @Description: 描述
* @Author: dzh
* @CreateDate: 2019-11-18 16:26
*/
public class TestServiceApi {
TestService testService;
@Inject
public TestServiceApi(Retrofit retrofit) {
testService = retrofit.create(TestService.class);
}
public Observable<Result<List<PublicEngModel>>> getNetData() {
return testService.getNetData(BaseConfig.APP_DOMAIN + "/app/public/english", false).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
}
5.发送请求
请求分为同步请求和异步请求
@Override
public void getNetData() {
serviceApi.getNetData()
.observeOn(AndroidSchedulers.mainThread())
.compose(getView().<Result<List<PublicEngModel>>>getBindToLifecycle())
.subscribe(new BaseRxObserver<Result<List<PublicEngModel>>>() {
@Override
protected void onError(ResponeThrowable e) {
mView.hideLoadingDialog();
getView().showToastMsg(e.message);
}
@Override
protected void onSuccess(Result<List<PublicEngModel>> response) {
// mView.hideLoadingDialog();
if (response.data != null) {
getView().onNetData(response.data);
}
}
});
}
上面是对代码的封装成功时走onSuccess(),失败的时候走onError()。
下图是传入URL规则的整合:
image.png注解
Retrofit还提供了很多其他的注解类型,我们常用的是@GET注解来发送Get请求,@POST注解来发送POST请求。下面列举主要的注解标识:
image.png1、网络请求方法
image.png1.@GET、@POST、@PUT、@DELETE、@HEAD分别对应 HTTP中的网络请求方式
2.@HTTP替换@GET、@POST、@PUT、@DELETE、@HEAD注解的作用 及 更多功能拓展
具体使用:通过属性method、path、hasBody进行设置
public interface TestService {
/**
* method:网络请求的方法(区分大小写)
* path:网络请求地址路径
* hasBody:是否有请求体
*/
@HTTP(method = "GET", path = "blog/{id}", hasBody = false)
Call<ResponseBody> getTestData(@Path("id") int id);
// {id} 表示是一个变量
// method 的值 retrofit 不会做处理,所以要自行保证准确
}
2、标记
! image.png1.@FormUrlEncoded
表示发送form-encoded的数据,每个键值对需要用@Filed来注解键名,随后的对象需要提供值。
2.@Multipart
表示发送form-encoded的数据(适用于 有文件 上传的场景),每个键值对需要用@Part来注解键名,随后的对象需要提供值。
public interface TestService {
/**
*表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
* <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值
*/
@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);
/**
* {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
* 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),
*/
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);
}
3、网络请求参数
image.png1.@Header & @Headers
添加请求头 &添加不固定的请求头
// @Header
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
// @Headers
@Headers("Authorization: authorization")
@GET("user")
Call<User> getUser()
// 以上的效果是一致的。
// 区别在于使用场景和使用方式
// 1\. 使用场景:@Header用于添加不固定的请求头,@Headers用于添加固定的请求头
// 2\. 使用方式:@Header作用于方法的参数;@Headers作用于方法
2.@Body
以 Post方式 传递 自定义数据类型 给服务器,如果提交的是一个Map,那么作用相当于 @Field,不过Map要经过 FormBody.Builder 类处理成为符合 Okhttp 格式的表单,如:
FormBody.Builder builder = new FormBody.Builder();
builder.add("key","value");
3.@Field & @FieldMap
发送 Post请求 时提交请求的表单字段,与 @FormUrlEncoded 注解配合使用
public interface TestService {
/**
* 表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
* <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值
*/
@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);
/**
* Map的key作为表单的键
*/
@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded2(@FieldMap Map<String, Object> map);
}
4.@Part & @PartMap
发送 Post请求 时提交请求的表单字段,与@Field的区别:功能相同,但携带的参数类型更加丰富,包括数据流,所以适用于 有文件上传 的场景,与 @Multipart 注解配合使用
public interface TestService {
/**
* {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
* 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),
*/
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);
/**
* PartMap 注解支持一个Map作为参数,支持 {@link RequestBody } 类型,
* 如果有其它的类型,会被{@link retrofit2.Converter}转换,如后面会介绍的 使用{@link com.google.gson.Gson} 的 {@link retrofit2.converter.gson.GsonRequestBodyConverter}
* 所以{@link MultipartBody.Part} 就不适用了,所以文件只能用<b> @Part MultipartBody.Part </b>
*/
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file);
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload3(@PartMap Map<String, RequestBody> args);
}
5.@Query和@QueryMap
用于 @GET 方法的查询参数(Query = Url 中 ‘?’ 后面的 key-value)如:url = [http://www.test.com/?type=android]=其中,Query = type配置时只需要在接口方法中增加一个参数即可:
@GET("/") // 其使用方式同 @Field与@FieldMap,这里不作过多描述
Call<String> cate(@Query("cate") String cate);
}
6.@Path
URL地址的缺省值
public interface TestService {
@GET("users/{user}/repos")
Call<ResponseBody> getNetBlog(@Path("user") String user );
// 访问的API是:https://api.test.com/users/{user}/repos
// 在发起请求时, {user} 会被替换为方法的第一个参数 user(被@Path注解作用)
}
7.@Url
直接传入一个请求的 URL变量 用于URL设置
public interface TestService {
@GET
Call<ResponseBody> testUrlAndQuery(@Url String url, @Query("showAll") boolean showAll);
// 当有URL注解时,@GET传入的URL就可以省略
// 当GET、POST...HTTP等方法中没有设置Url时,则必须使用 {@link Url}提供
}
至此Retrofit的使用就大致介绍完毕了!