Android中Retrofit2使用入門
簡介
Retrofit2是square公司開源的網路庫,該公司的另一個庫Okhttp,相信大家應該同樣熟悉,在Retrofit流行之前,Okhttp是我們使用比較多的幾個網路庫之一。Retrofit雖然時下最流行,其實並沒有替代Okhttp,Retrofit預設還是基於Okhttp去完成底層網路處理的,只是在上層做了進一步的封裝,使開發者更易使用而已。本篇我們就來談一談Retrofit2的使用。
示例引入
新增依賴
dependencies {
compile 'com.squareup.retrofit2:retrofit:2.0.2'
}
Retrofit例項化
最基本的Retrofit建立:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:6666/")
.build();
介面定義
使用@GET定義了一個查詢介面:
public interface AdsService {
@GET("ads")
Call<ResponseBody> getAds();
}
介面呼叫
呼叫getAds介面,並設定監聽回撥:
Call<ResponseBody> call = service.getAds ();
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace ();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
註解介紹
Retrofit很重要的一個特色就是,使用註解配置網路引數,非常方便和優雅。
註解可以分為三類:
1、HTTP請求方法類
POST、DELETE、PUT、GET、HEAD、PATCH、OPTIONS、HTTP
下面以常用的GET、POST方法,以及比較特殊的HTTP註解為例來說明。
GET
@GET("ads")
Call<ResponseBody> getAds();
POST
@POST("login")
@FormUrlEncoded
Call<ResponseBody> login(@Field("username") String name, @Field("password") String pwd);
HTTP
HTTP可以替換其他7個註解使用:
@HTTP(method = "GET", path = "ads", hasBody = false)
Call<ResponseBody> getAds();
2、標記類
FormUrlEncoded
表示請求提是一個form表單,和Field、FieldMap配合使用
Multipart
表示請求體是一個支援檔案上傳的form表單,和Part、PartMap配合使用
Streaming
表示響應體的資料用流的形式返回
3、引數類
用於方法
這裡就一個註解:Headers
@GET("ads")
@Headers({"headerName1: headerValue1", "headerName2: headerValue2"})
Call<ResponseBody> getAds();
用於方法引數
Path
@HTTP(method = "GET", path = "ads/{id}", hasBody = false)
Call<ResponseBody> getAd(@Path("id") int id);
Url
@GET
Call<ResponseBody> getAd(@Url String url, @Query("id") int id);
注:使用了Url註解,請求方法中就無需配置url引數了
Query和QueryMap
@GET("ads")
Call<ResponseBody> getAd(@Query("id") int id);
@GET("ads")
Call<ResponseBody> getAds(@QueryMap Map<String, String> map);
Field和FieldMap
@POST("login")
@FormUrlEncoded
Call<ResponseBody> login(@Field("username") String name, @Field("password") String pwd);
//或者寫成這樣
@POST("login")
@FormUrlEncoded
Call<ResponseBody> login(@QueryMap Map<String, String> map);
Header
@GET("ads")
Call<ResponseBody> getAds(@Header("headerName") String headerValue);
Part和PartMap
@POST("upload")
@Multipart
Call<ResponseBody> uploadFile1(@Part("name") RequestBody name, @Part MultipartBody.Part file);
@POST("upload")
@Multipart
Call<ResponseBody> uploadFile2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file);
使用Converter
這裡只以常用的GsonConverter為例
新增converter-gson庫依賴
dependencies {
compile 'com.squareup.retrofit2:converter-gson:2.0.2' //gson轉換器,將JSON資料對映為物件
compile 'com.google.code.gson:gson:2.2.4' //Gson解析庫
}
新增GsonConverterFactory
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())//請求的結果轉為實體類
.build();
介面修改
public interface AdsService {
@GET("ads")
Call<AdResult> getAds();
}
這裡的AdResult對應JSON對映的物件
介面呼叫
Call<AdResult> call = service.getAds();
call.enqueue(new Callback<AdResult>() {
@Override
public void onResponse(Call<AdResult> call, Response<AdResult> response) {
if (response != null && response.isSuccessful()) {
}
}
@Override
public void onFailure(Call<AdResult> call, Throwable t) {
}
});
使用CallAdapter
這裡只以常用的RxJava2CallAdapter為例
新增RxJava依賴
dependencies {
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' //RxJava2CallAdapter
compile 'io.reactivex.rxjava2:rxjava:2.1.3'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
}
新增RxJava2CallAdapterFactory
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
介面修改
public interface AdsService {
@GET("ads")
Flowable<Response<AdResult>> getAds();
}
這裡的Response是retrofit2.Response,便於獲取Response狀態資訊。
介面呼叫
Flowable<Response<AdResult>> flowable = service.getAds();
flowable.map(new Function<Response<AdResult>, List<Ad>>() {
@Override
public List<Ad> apply(Response<AdResult> retrofitResponse) throws Exception {
if (retrofitResponse != null && retrofitResponse.isSuccessful()) {
return list;
}
return null;
}
}).subscribeOn(SchedulerProvider.getInstance().io())
.observeOn(SchedulerProvider.getInstance().ui())
.subscribe(new DefaultSubscriber<List<Ad>>() {
@Override
public void onNext(List<Ad> ads) {
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
});
新增Interceptor
日誌Interceptor
如果使用了gson解析,列印網路請求和響應的日誌,就沒那麼方便了,實際的網路操作都被封裝起來了。我們需要使用squareup提供的另一個庫來滿足列印日誌的需求,所以還要新增logging-interceptor庫依賴。
新增依賴
dependencies {
compile 'com.squareup.okhttp3:logging-interceptor:3.6.0' //日誌攔截器
}
設定Interceptor
private Api() {
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.readTimeout(30, TimeUnit.SECONDS)
.connectTimeout(30, TimeUnit.SECONDS)
.retryOnConnectionFailure(true);
if (BuildConfig.DEBUG) {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new AdsLogger());
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
builder.addInterceptor(loggingInterceptor);
}
...
}
private static class AdsLogger implements HttpLoggingInterceptor.Logger {
@Override
public void log(String message) {
Log.i("RetrofitLog", "" + message);
}
}
這裡,我們可以通過BuildConfig.DEBUG控制是否支援日誌列印。
總結
以上大概就是本人目前學習Retrofit2的一點心得,談不上深入,也沒有具體到專案,只能算是入門教程,存在錯誤的地方,希望指正。
參考資料
你真的會用Retrofit2嗎?Retrofit2完全教程
Retrofit列印請求地址和返回內容
Retrofit — Getting Started and Creating an Android Client