1. 程式人生 > >Android中Retrofit2使用入門

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);
    @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