什麼是 Retrofit ?
Retrofit是Square開發的一個Android和Java的REST客戶端庫。這個庫非常簡單並且具有很多特性,相比其他的網絡庫,更容易讓初學者快速掌握。它可以處理GET、POST、PUT、DELETE…等請求,還可以使用picasso加載圖片。
常用註解
Retrofit 2.0底層依賴OkHttp實現,也就是說Retrofit本質上就是對OkHttp的更進一步封裝。Retrofit和其它Http庫最大區別在於通過大範圍使用註解簡化Http請求。
Retrofit使用註解來描述HTTP請求:
- URL參數的替換和query參數的支持
- 對象轉化爲請求體(如:JSON,protocol buffers等)
- 多重請求體和文件上傳
Retrofit中的註解大體分爲以下幾類:用於標註請求方式的註解、用於標記請求頭的註解、用於標記請求參數的註解。其實,任何一種Http庫都提供了相關的支持,無非在retrofit中是用註解來簡化。
請求方法註解
該類型的註解用於標註不同的http請求方式,主要有以下幾種:
註解 | 說明 |
---|---|
@GET | 表明這是get請求 |
@POST | 表明這是post請求 |
@PUT | 表明這是put請求 |
@DELETE | 表明這是delete請求 |
@PATCH | 表明這是一個patch請求,該請求是對put請求的補充,用於更新局部資源 |
@HEAD | 表明這是一個head請求 |
@OPTIONS | 表明這是一個option請求 |
@HTTP | 通用註解,可以替換以上所有的註解,其擁有三個屬性:method,path,hasBody |
簡單用例:
@GET("mobile/capture")
Call<ResponseBody> getCapture(@Query("phone") String phone);
請求頭註解
該類型的註解用於爲請求添加請求頭。
註解 | 說明 |
---|---|
@Headers | 用於添加固定請求頭,可以同時添加多個。通過該註解添加的請求頭不會相互覆蓋,而是共同存在 |
@Header | 作爲方法的參數傳入,用於添加不固定值的Header,該註解會更新已有的請求頭 |
@Headers的示例:
//使用@Headers添加單個請求頭
@Headers("Cache-Control:public,max-age=120")
@GET("mobile/active")
Call<ResponseBody> getActive(@Query("id") int activeId);
//使用@Headers添加多個請求頭
@Headers({
"User-Agent:android"
"Cache-Control:public,max-age=120",
})
@GET("mobile/active")
Call<ResponseBody> getActive(@Query("id") int activeId);
@Header的示例:
@GET("mobile/active")
Call<ResponseBody> getActive(@Header("token") String token,@Query("id") int activeId);
可以看出@Header是以方法參數形勢傳入的
請求和響應格式註解
該類型的註解用於標註請求和響應的格式。
名稱 | 說明 |
---|---|
@FormUrlEncoded | 表示請求發送編碼表單數據,每個鍵值對需要使用@Field註解 |
@Multipart | 表示請求發送multipart數據,需要配合使用@Part |
@Streaming | 表示響應用字節流的形式返回.如果沒使用該註解,默認會把數據全部載入到內存中.該註解在在下載大文件的特別有用 |
請求參數類註解
該類型的註解用來標註請求參數的格式,有些需要結合上面請求和響應格式的註解一起使用。
名稱 | 說明 |
---|---|
@Body | 多用於post請求發送非表單數據,比如想要以post方式傳遞json格式數據 |
@Filed | 多用於post請求中表單字段,Filed和FieldMap需要FormUrlEncoded結合使用 |
@FiledMap | 和@Filed作用一致,用於不確定表單參數 |
@Part | 用於表單字段,Part和PartMap與Multipart註解結合使用,適合文件上傳的情況 |
@PartMap | 用於表單字段,默認接受的類型是Map |
Retrofit2基本使用
先定義一個接口
public interface PersonalProtocol {
/**
* 用戶信息
* @param page
* @return
*/
@FormUrlEncoded
@POST("user/personal_list_info")
Call<Response<PersonalInfo>> getPersonalListInfo(@Field("cur_page") int page);
}
@FormUrlEncoded
註解表示from表單,另外還有@Multipart
等註解,如果接口不需要傳遞參數,那麼@FormUrlEncoded
以及@Multipart
需要去掉
現在看看Retrofit
的使用
private void requestRetrofit(){
Retrofit retrofit = new Retrofit.Builder().baseUrl("www.xxxx.com/").build();
PersonalProtocol personalProtocol = retrofit.create(PersonalProtocol.class);
Call<Response<PersonalInfo>> call = personalProtocol.getPersonalListInfo(12);
call.enqueue(new Callback<Response<PersonalInfo>>() {
@Override
public void onResponse(Call<Response<PersonalInfo>> call, Response<Response<PersonalInfo>> response) {
//數據請求成功
}
@Override
public void onFailure(Call<Response<PersonalInfo>> call, Throwable t) {
//數據請求失敗
}
});
}
首先將域名傳入構造一個Retrofit
,然後通過retrofit
中的create
方法傳入一個Java接口並得到一個PersonalProtocol
(當然PersonalProtocol
這個對象是經過處理了的,這個後面會講到)調用getPersonalListInfo(12)
然後返回一個Call
,最後這個Call
調用了enqueue
方法去異步請求http,這就是一個基本的Retrofit
的網絡請求。Retrofit2
中Call
接口的默認實現是OkHttpCall
,它默認使用OkHttp3
作爲底層http
請求client
。
其實Retrofit還有很多方法,我們現在選兩個一起來看看:
OkHttpClient okHttpClient = new OkHttpClient();
Retrofit retrofit = new Retrofit.Builder().baseUrl("www.xxxx.com")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(buildGson()))
.build();
addConverterFactory
方法中使用了gson
去解析json
此外,我們再來看看RxJava的使用:
OkHttpClient okHttpClient = new OkHttpClient();
Retrofit retrofit = new Retrofit.Builder().baseUrl("www.xxxx.com")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(buildGson()))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
addCallAdapterFactory
方法中使用了RxJavaCallAdapterFactory
,網絡請求也需要修改:
PersonalProtocol personalProtocol = retrofit.create(PersonalProtocol.class);
rx.Observable<PersonalInfo> observable = personalProtocol.getPersonalListInfo(12);
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())//最後在主線程中執行
.subscribe(new Subscriber<PersonalInfo>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
//請求失敗
}
@Override
public void onNext(PersonalInfo personalInfo) {
//請求成功
}
});
同時PersonalProtocol
接口也需要改變:
public interface PersonalProtocol {
/**
* 用戶信息
* @param page
* @return
*/
@FormUrlEncoded
@POST("user/personal_list_info")
Observable<PersonalInfo> getPersonalListInfo(@Field("cur_page") int page);
// Call<Response<PersonalInfo>> getPersonalListInfo(@Field("cur_page") int page);
}