添加权限
manifest文件添加网络权限
<uses-permission android:name="android.permission.INTERNET"/>
添加依赖
主库
dependencies {
implementation ‘com.squareup.retrofit2:retrofit:2.0.2’// Retrofit库
}
扩展数据转换器
如请求类型和json模型的互转(此依赖一般都要添加):
implementation ‘com.squareup.retrofit2:converter-gson:2.0.2’
其他如下:
数据解析器 | Gradle依赖 |
---|---|
Gson | :converter-gson:2.0.2 |
Jackson | :converter-jackson:2.0.2 |
Simple XML | :converter-simplexml:2.0.2 |
Protobuf | :converter-protobuf:2.0.2 |
Moshi | :converter-moshi:2.0.2 |
Wire | :converter-wire:2.0.2 |
Scalars | :converter-scalars:2.0.2 |
扩展调用适配器(CallAdapter)
retrofit除了内置默认的DefaultCallAdapterFactory,支持调用服务方法返回类型Call外,
也支持其他网络请求适配器方式:guava、Java8和rxjava。
适配器简称 | 依赖路径 | 支持的返回类型 |
---|---|---|
guava | :adapter-guava:2.0.2 | |
Java8 | :adapter-java8:2.0.2 | |
rxjava | :adapter-rxjava:2.0.2 | Observable、Flowable等 |
创建 接收服务器返回数据 的模型
如:
public class AppRequestResult<T> {
private int code;
private T data;
private String msg;
}
创建 用于描述网络请求 的接口
你需要定义一个接口,然后在该接口内定义用来描述请求的方法,如:
public interface Api {}
以下第一类的注解用于标注方法的请求方式,如get、post等。第二类的注解用于标注请求数据的组织方式。第三类注解用于标注不同的数据。
根据接口的请求方法查看下面对应的注解的使用介绍,如get请求方式的接口请查看@Get的内容。
请求地址的构成
一个请求的URL可以通过 替换块 和 请求方法的参数 实现动态更新。网络请求的完整 Url =在创建Retrofit实例时通过.baseUrl()设置的基本url(以下称预置的基本url) +网络请求接口的注解设置(下面称 “path“ ),但是当path中包含完整的url地址时(以http开头),请求时预置的基本url会被忽略。
无请求体的请求方式:DELETE、GET、HEAD、OPTIONS。
有请求体的请求方式:PATCH、POST、PUT。
第一类:HTTP请求方法
@HTTP
作用:替换**@GET、@POST、@PUT、@DELETE、@HEAD**注解的作用 及 更多功能拓展
具体使用:通过属性method、path、hasBody进行设置
例子:
/**
* method:网络请求的方法(区分大小写)
* path:网络请求地址路径
* hasBody:是否有请求体
*/
@HTTP(method = "GET", path = "blog/{id}", hasBody = false)
Call<ResponseBody> getCall(@Path("id") int id);
// {id} 表示是一个变量
// method 的值 retrofit 不会做处理,所以要自行保证准确
@Get
get请求。假设baseUrl=http://192.168.43.173/api/。
1、没有参数:http://192.168.43.173/api/trades
@GET(“trades”)
Call getItem();
2、URL中带有参数:http://192.168.43.173/api/trades/{userId}
@GET(“trades/{userId}”)
Call getItem(@Path(“userId”) String userId);
3、参数在url问号之后:http://192.168.43.173/api/trades?userId={用户id}
@GET(“trades”)
Call getItem(@Query(“userId”) String userId, @QueryMap Map<String, String> map);
@Post
post请求。
1、补全url和url后的参数,添加一条表单数据:
http://192.168.43.173/api/trades/{userId}?token={token}
@FormUrlEncoded
@POST(“trades/{userId}”)
Call postResult(@Path(“userId”) String userId, @Query(“token”) String token, @Field(“reason”) String reason);
2、post一个对象
1)@POST(“trades”)
Call postResult(@Body TradesBean bean);
2)@POST(“trades/{userId}”)
Call postResult(@Part(“entity”) TradesBean bean);
@Put
put请求
1、put一个实体
@PUT(“trade/carInfo/{pid}”)
Call putInfo(
@Path(“pid”) Int pid,
@Body CarInfoBean carInfoBean;)
@Delete
方法注解。DELETE请求。
例子:补全路径。
@DELETE(“trades/{userId}”)
Call deleteInfo(
@Path(“userId”) String userId,
@Query(“token”) String token);
@HEAD
方法注解。HEAD请求。
@PATCH
方法注解。PATCH请求。
@OPTIONS
方法注解。OPTIONS请求。
第二类:标记类
@FormUrlEncoded
作用:表示请求体是一个表单。每个键值对需要用@Filed来注解键名,随后的对象需要提供值。
@POST(“form”)
@FormUrlEncoded
Call request(@Field(“username”) String name, @Field(“age”) int age);
注意:不能与@Multipart注解一起用。
@Multipart
作用:表示请求体是多部分组成。
@POST("/form")
@Multipart
Call testFileUpload1(@Part(“name”) RequestBody name, @Part(“age”) RequestBody age, @Part MultipartBody.Part file);
注意:不能与@FormUrlEncoded注解一起用。
@Streaming
作用:表示将响应体的数据以流的形式返回;适用于返回数据较大的场景。如果没有使用该注解,默认把数据载入内存,之后数据也是从内存读取。
第三类:参数类
@Header & @Headers
作用:@Header为参数注解。@Headers为方法注解。添加请求头 &添加不固定的请求头。
例子:
@GET(“user”)
Call getUser(@Header(“Authorization”) String authorization)
//@Headers(“Cache-Control: max-age=640000”)
@Headers({
“X-Foo: Bar”,
“X-Ping: Pong”
})
@GET("/")
…
注意:声明1个以上的@Headers注解会导致其中一个无效。值格式:”name1:value1”,”name2:value2”。当存在name为Content-Type的header时,会修改整个请求的MediaType。
@HeaderMap
例子:
@GET("/search")
void list(@HeaderMap Map<String, String> headers);
注意:后面跟随的类型必须是Map,且key类型必须为String。
@Body
作用:当你想直接控制POST/PUT请求的请求体,此对象会使用retrofit的转换器序列化然后直接设置到请求的请求体。
注意:不能和@FormUrlEncoded和@Multipart一起使用。一个方法内只能声明一个该注解。
@Field & @FieldMap
作用:用于表单字段
具体使用:只能与 @FormUrlEncoded 注解配合使用,参数类型可以是Iterable<具体类型>、具体类型[]或具体类型。FieldMap接受的类型是Map<String, String>,非String类型会调用其toString方法。
@POST("/form")
@FormUrlEncoded
Call testFormUrlEncoded1(@Field(“username”) String name, @Field(“age”) int age);
@POST("/form")
@FormUrlEncoded
Call testFormUrlEncoded2(@FieldMap Map<String, String> map);
注意:@FieldMap后面跟随的类型必须是Map,且key类型必须为String。
@Part & @PartMap
作用:必须与 @Multipart 注解配合使用,适合有文件上传的场景。与@Field的区别:功能相同,但携带的参数类型更加丰富,包括数据流。
当@Part的名称值为空时,后面的类型可以是Iterable<MultipartBody.Part>、MultipartBody.Part[]、MultipartBody.Part。当@Part的名称有值时,用于提交表单数据,后面的类型可以是MultipartBody.Part之外的其他类型,如Iterable、String[]、String。
@Multipart
@POST("/")
Call example(
@Part(“description”) String description,
@Part(value = “image”, encoding = “8-bit”) RequestBody image);
当值类型是 okhttp3.MultipartBody.Part时,其内容会被直接使用。当值类型为RequestBody时,会直接使用他的内容类型,名称取注解声明的。其他类型会被转换器转换成合适的表示,名称取注解声明的。
@PartMap 注解后面的类型必须是Map<String, MultipartBody.Part之外的其他类型>。
@Multipart
@POST("/upload")
Call upload(
@Part(“file”) RequestBody file,
@PartMap Map<String, RequestBody> params);
当值类型为RequestBody时,会直接使用他的内容类型。其他类型会被转换器转换成合适的表示。map类型的key-value都不能为null。
@Query和@QueryMap
作用:用于 @GET 方法的查询参数。如:http://www.println.net?cate=android中的查询参数cate。
具体使用:配置时只需要在接口方法中增加一个参数即可:
@GET(“abc”)
Call cate(@Query(“cate”) String cate, @QueryMap Map<String, String> map);
注意:后面跟随的类型如果是List等列表,则必须指定泛型的具体类型,如List。
@QueryMap跟随的类型必须是Map类型,且key类型必须为String。
@QueryName
指定url的?后没有值的查询参数名称。
1、简单示例:
@GET("/friends")
Call friends(@QueryName String filter);
使用foo.friends(“contains(Bob)”)调用会产生/friends?contains(Bob) 。
2、数组/可变参数示例:
@GET("/friends")
Call friends(@QueryName String… filters);
调用foo.friends(“contains(Bob)”, “age(42)”)产生/friends?contains(Bob)&age(42) 。
3、默认情况下,参数名称是 URL 编码的。 指定encoded=true以更改此行为。
@GET("/friends")
Call friends(@QueryName(encoded=true) String filter);
使用foo.friends(“name+age”))调用会产生/friends?name+age 。
@Path
作用:URL地址的缺省值
具体使用:
@GET(“users/{u}/repos”)
Call getBlog(@Path(“u”) String user );
注意:@Path不能和@Url一起使用。不能在@Query、@QueryName、@QueryMap之后声明。存在@Path声明时,方法注解后的url不能为空。
@Url
值:okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri其中一种类型。
作用:绝对或相对url。
使用:
@GET
Call testUrlAndQuery(@Url String url, @Query(“showAll”) boolean showAll);
注意:@Path不能和@Url一起使用。不能在@Query、@QueryName、@QueryMap之后声明。当有@Url时,@GET后面的URL必须为空。
其他类
@Tag
为请求打上标签
@GET("/")
Call foo(@Tag String tag);
注意:一个方法可设置多个不同类型参数的标签,不允许出现重复类型的@Tag。
创建 Retrofit 实例
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.addInterceptor(this.publicParamInterceptor)
.addInterceptor(logInterceptor);
this.retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
//.addCallAdapterFactory(RxJavaCallAdapterFactory.create())//需要方法返回Observable时使用
.client(builder.build())
.baseUrl(baseUrl)
.validateEagerly(true)
.build();
可设置参数
请求客户端
用于请求的客户端。这是一个调用callFactory的方便方法。
client(OkHttpClient client)
调用工厂(请求客户端的接口)
为创建Call实例指定一个自定义的调用工厂。
callFactory(okhttp3.Call.Factory factory)
API基本url
应该以”/”结尾。具体见注释。
baseUrl(URL baseUrl)
转换工厂
用于对象的序列化和反序列化。
addConverterFactory(Converter.Factory factory)
调用适配器工厂
用于支持服务方法返回除了Call以外的类型。
addCallAdapterFactory(CallAdapter.Factory factory)
回调执行器
从你的服务方法返回Call时,执行器在Callback方法中被调用。
callbackExecutor(Executor executor)
是否马上验证
validateEagerly(boolean validateEagerly)。是否在调用create(Class)创建接口实例时就检测接口的方法定义地是否正确,而不是在调用方法时才检测。默认false。
创建 网络请求接口实例
Api api = retrofit.create(Api.class);
发送网络请求(异步 / 同步)
Call<RequestResult> call = api.getA(...);
//发送网络请求(异步)
call.enqueue(new Callback<Translation>() {
//请求成功时回调
@Override
public void onResponse(Call<Translation> call, Response<Translation> response) {
//请求处理,输出结果
response.body().show();
}
//请求失败时候的回调
@Override
public void onFailure(Call<Translation> call, Throwable throwable) {
System.out.println("连接失败");
}
});
// 发送网络请求(同步)
Response<RequestResult> response = call.execute();
扩展
自定义Converter
参考GsonConverterFactory类的实现。
Retrofit retrofit = new Retrofit.Builder()
...
// 我们自定义的一定要放在其他的Converter前面
.addConverterFactory(GsonConverterFactory.create())
.build();
注:addConverterFactory是有先后顺序的,如果有多个ConverterFactory都支持同一种类型,那么就是只有第一个才会被使用,而GsonConverterFactory是不判断是否支持的,所以这里若交换了顺序还会有一个异常抛出,原因是类型不匹配。
自定义CallAdapter
参考RxJavaCallAdapterFactory类。