配置
满足以下需求
网络请求使用自定义的OkHttpClient
对于Json的解析使用Gson
返回结果支持RxJava
-
服务器返回数据格式为
{ //请求code 1000为成功 "code": Integer, //请求信息 "message": String, //请求的数据体 "data": Object }
添加依赖
//retrofit2
compile 'com.squareup.retrofit2:retrofit:2.2.0'
//okhttp
compile 'com.squareup.okhttp3:okhttp:3.7.0'
//okhttp 网络请求log 拦截器
compile 'com.squareup.okhttp3:logging-interceptor:3.7.0'
//gson
compile 'com.google.code.gson:gson:2.8.0'
//gson 数据解析适配器
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
//RxJava2
compile 'io.reactivex.rxjava2:rxjava:2.0.9'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
//RxJava2 请求结果适配器
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
基本使用流程
配置OkHttpClient
public class Client {
private static OkHttpClient mOkHttpClient;
private final static HttpLoggingInterceptor HTTP_LOGGING_INTERCEPTOR =
new HttpLoggingInterceptor(message -> Log.d("Http:", message))
.setLevel(HttpLoggingInterceptor.Level.BODY);
/**
* 因为设置了读写超时,该client不适用于上传和下载
*/
public static OkHttpClient get() {
if (mOkHttpClient == null) {
mOkHttpClient = new OkHttpClient.Builder()
//log 拦截器
.addInterceptor(HTTP_LOGGING_INTERCEPTOR)
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30,TimeUnit.SECONDS)
.build();
}
return mOkHttpClient;
}
}
定义Retrofit
public class Retrofits {
private static Retrofit mRetrofit;
public static Retrofit get() {
if(mRetrofit == null){
mRetrofit = new Retrofit.Builder()
.baseUrl(BuildConfig.BASE_SERVER)
.client(Client.get())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
return mRetrofit;
}
public static <T> T get(Class<T> tClass){
return get().create(tClass);
}
}
定义Model
-
BaseResult
public class BaseResult<T> { private int code; private String message; private T data; public boolean isSuccess(){ return code == 1000; } //此处省略getter 和 setter }
-
ServerInfo
public class ServerInfo { private int versionCode; private String versionName; //此处省略getter 和 setter }
定义API接口
public interface Api {
@GET("/test/getServerInfo")
Observable<BaseResult<ServerInfo>> getServerInfo();
}
发起网络请求
Retrofits.get(Api.class)
.getServerInfo()
//指定在IO线程进行网络请求
.subscribeOn(Schedulers.io())
//指定订阅者在UI线程响应
.observeOn(AndroidSchedulers.mainThread())
//处理结果
.subscribe(result -> {
if (result.isSuccess()) {
Toast.makeText(this,
result.getData().toString(),
Toast.LENGTH_SHORT)
.show();
}else {
Toast.makeText(this,
String.format("失败:%s", result.getMessage()),
Toast.LENGTH_SHORT)
.show();
}
});
Retrofit说明
注解说明
Body
- 用作位置:参数(不可以为null)
- 参数:无
- 场景:post或者put上传Json数据。直接将一个实体类,通过序列化为Json字串作为网络请求参数
注:此处所使用的序列化通过.addConverterFactory()
进行配置,前文Demo使用的是Gson
示例:
//实体
class Repo {
final String owner;
final String name;
...
}
interface Api{
...
@POST("/")
Observable<BaseResult<Body>> sendNormal(@Body Repo repo);
...
}
Field
作用位置:参数
-
参数
参数 类型 必选 说明 value String 是 key名 encoded boolean 否 是否使用 URL encoded,默认false 场景:使用表单进行数据上传时。
原理:String.valueOf()把参数值转换为String,然后进行URL编码,当参数值为null值时,会自动忽略,如果传入的是一个List或array,则为每一个非空的item拼接一个键值对,每一个键值对中的键是相同的,值就是非空item的值,如: name=张三&name=李四&name=王五,另外,如果item的值有空格,在拼接时会自动忽略,例如某个item的值为:张 三,则拼接后为name=张三
示例:
@POST("/")
Call<ResponseBody> sample(@Field("name") String name);
@POST("/list")
Call<ResponseBody> sample(@Field("name") String... names);
FieldMap
作用位置:参数
-
参数
参数 类型 必选 说明 encoded boolean 否 是否使用 URL encoded,默认false 场景:用于表单数据参数。将Map数据转成对应的表单数据
示例:
@POST("/things")
Call<ResponseBody> things(@FieldMap Map<String, String> fields);
Header
用于位置:参数
-
参数
参数 类型 必选 说明 value String 是 对应Header的key
- 场景:用作传入某个header
示例
@GET("/")
Call<ResponseBody> foo(@Header("Accept-Language") String lang);
HeaderMap
- 作用位置:参数
- 参数:无
- 场景:以map方式同时传入多个Header
示例:
@GET("/search")
Call<ResponseBody> list(@HeaderMap Map<String, String> headers);
Headers
用作位置:方法
-
参数 类型 必选 说明 value String[] 是 对应Header的key 参数:
参数 类型 必选 说明 value String[] 是 对应Header的key 场景:对于某个请求,默认一个到多个的header
示例:
@Headers("Cache-Control: max-age=640000")
@GET("/")
...
@Headers({
"X-Foo: Bar",
"X-Ping: Pong"
})
@GET("/")
...
Path
用作位置:参数
-
参数
参数 类型 必选 说明 value String 是 对应Url替换部分 encoded boolean 否 是否进行URL encoded,默认false 场景:变化的URL进行请求
示例:
@GET("/user/{name}")
Call<ResponseBody> encoded(@Path("name") String name);
@GET("/user/{name}")
Call<ResponseBody> notEncoded(@Path(value="name", encoded=true) String name);
Query
用作位置:参数
-
参数
参数 类型 必选 说明 value String 是 key名 encoded boolean 否 是否进行URL encoded,默认false 场景:拼接URL查询key-value
示例
@GET("/friends")
Call<ResponseBody> friends(@Query("page") int page);
如果调用传入参数为1
,则请求URL为/friends?page=1
@GET("/friends")
Call<ResponseBody> friends(@Query("group") String... groups);
如果调用传入参数为["1","2","3"]
,则请求URL为/friends?group=1&group=2&group=3
QueryMap
用作位置:参数
-
参数:
参数 类型 必选 说明 encoded boolean 否 是否进行URL encoded,默认false 场景:以map方式传值,拼接URL查询key-value
示例:
@GET("/friends")
Call<ResponseBody> friends(@QueryMap Map<String, String> filters);
RxJava配置
对于Rx的配置通过Retrofit.Builder.addCallAdapterFactory
进行设置的。
Retrofit提供了RxJava2CallAdapterFactory
类来进行构建。
需要注意的是RxJava2CallAdapterFactory
中需要配置网络请求的执行方式。目前提供以下3种
-
同步执行
RxJava2CallAdapterFactory.create()
-
异步执行
此种方式一般是将网络请求线程交由OkHttp自己的线程池进行调度
RxJava2CallAdapterFactory.createAsync()
-
指定调度器(Scheduler)执行
RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io())