配置
滿足以下需求
網(wǎng)絡請求使用自定義的OkHttpClient
對于Json的解析使用Gson
返回結(jié)果支持RxJava
-
服務器返回數(shù)據(jù)格式為
{ //請求code 1000為成功 "code": Integer, //請求信息 "message": String, //請求的數(shù)據(jù)體 "data": Object }
?
添加依賴
//retrofit2
compile 'com.squareup.retrofit2:retrofit:2.2.0'
//okhttp
compile 'com.squareup.okhttp3:okhttp:3.7.0'
//okhttp 網(wǎng)絡請求log 攔截器
compile 'com.squareup.okhttp3:logging-interceptor:3.7.0'
//gson
compile 'com.google.code.gson:gson:2.8.0'
//gson 數(shù)據(jù)解析適配器
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 請求結(jié)果適配器
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();
}
發(fā)起網(wǎng)絡請求
Retrofits.get(Api.class)
.getServerInfo()
//指定在IO線程進行網(wǎng)絡請求
.subscribeOn(Schedulers.io())
//指定訂閱者在UI線程響應
.observeOn(AndroidSchedulers.mainThread())
//處理結(jié)果
.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
- 用作位置:參數(shù)(不可以為null)
- 參數(shù):無
- 場景:post或者put上傳Json數(shù)據(jù)。直接將一個實體類,通過序列化為Json字串作為網(wǎng)絡請求參數(shù)
注:此處所使用的序列化通過.addConverterFactory()
進行配置,前文Demo使用的是Gson
示例:
//實體
class Repo {
final String owner;
final String name;
...
}
interface Api{
...
@POST("/")
Observable<BaseResult<Body>> sendNormal(@Body Repo repo);
...
}
Field
作用位置:參數(shù)
-
參數(shù)
參數(shù) 類型 必選 說明 value String 是 key名 encoded boolean 否 是否使用 URL encoded,默認false 場景:使用表單進行數(shù)據(jù)上傳時。
原理:String.valueOf()把參數(shù)值轉(zhuǎn)換為String,然后進行URL編碼,當參數(shù)值為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
作用位置:參數(shù)
-
參數(shù)
參數(shù) 類型 必選 說明 encoded boolean 否 是否使用 URL encoded,默認false 場景:用于表單數(shù)據(jù)參數(shù)。將Map數(shù)據(jù)轉(zhuǎn)成對應的表單數(shù)據(jù)
示例:
@POST("/things")
Call<ResponseBody> things(@FieldMap Map<String, String> fields);
Header
用于位置:參數(shù)
-
參數(shù)
參數(shù) 類型 必選 說明 value String 是 對應Header的key
- 場景:用作傳入某個header
示例
@GET("/")
Call<ResponseBody> foo(@Header("Accept-Language") String lang);
HeaderMap
- 作用位置:參數(shù)
- 參數(shù):無
- 場景:以map方式同時傳入多個Header
示例:
@GET("/search")
Call<ResponseBody> list(@HeaderMap Map<String, String> headers);
Headers
用作位置:方法
-
參數(shù) 類型 必選 說明 value String[] 是 對應Header的key 參數(shù):
參數(shù) 類型 必選 說明 value String[] 是 對應Header的key 場景:對于某個請求,默認一個到多個的header
示例:
@Headers("Cache-Control: max-age=640000")
@GET("/")
...
@Headers({
"X-Foo: Bar",
"X-Ping: Pong"
})
@GET("/")
...
Path
用作位置:參數(shù)
-
參數(shù)
參數(shù) 類型 必選 說明 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
用作位置:參數(shù)
-
參數(shù)
參數(shù) 類型 必選 說明 value String 是 key名 encoded boolean 否 是否進行URL encoded,默認false 場景:拼接URL查詢key-value
示例
@GET("/friends")
Call<ResponseBody> friends(@Query("page") int page);
如果調(diào)用傳入?yún)?shù)為1
,則請求URL為/friends?page=1
@GET("/friends")
Call<ResponseBody> friends(@Query("group") String... groups);
如果調(diào)用傳入?yún)?shù)為["1","2","3"]
,則請求URL為/friends?group=1&group=2&group=3
QueryMap
用作位置:參數(shù)
-
參數(shù):
參數(shù) 類型 必選 說明 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
類來進行構(gòu)建。
需要注意的是RxJava2CallAdapterFactory
中需要配置網(wǎng)絡請求的執(zhí)行方式。目前提供以下3種
-
同步執(zhí)行
RxJava2CallAdapterFactory.create()
-
異步執(zhí)行
此種方式一般是將網(wǎng)絡請求線程交由OkHttp自己的線程池進行調(diào)度
RxJava2CallAdapterFactory.createAsync()
-
指定調(diào)度器(Scheduler)執(zhí)行
RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io())
?