Android Retrofit + RxJava使用詳解

1.Retrofit基本使用

首先來了解下Retrofit是什麼,在官網中對於Retrofit的描述是這樣的:

A type-safe HTTP client for Android and Java.

適用於Android和Java的類型安全的HTTP客戶端。

可以理解成一個封裝好的網絡請求庫。

Retrofit GitHub地址

接下來學習一下Retrofit的基本使用方法:

在app根目錄的build.gradle文件中加入依賴:

compile 'com.squareup.retrofit2:retrofit:2.3.0'

創建實體類:

我們使用http://www.kuaidi100.com/query?type=yuantong&postid=11111111111這個快遞接口來測試,根據返回數據創建實體類,類名爲PostInfo,在這裏就不貼代碼了,可以在文末下載Demo查看代碼。

定義請求參數接口:

public interface RetrofitService {

    /**
     * 獲取快遞信息
     *
     * @param type   快遞類型
     * @param postid 快遞單號
     * @return Call<PostInfo>
     */
    @GET("query")
    Call<PostInfo> getPostInfo(@Query("type") String type, @Query("postid") String postid);
}

定義一個接口RetrofitService,和普通的接口類相同,在裏面定義一個方法getPostInfo,可以看到這個方法使用了@GET(“query”)註解,代表這是一個GET請求,請求接口爲query(完整請求地址中域名/到?之間的字段),方法返回值爲Call實體,這個稍後會用於具體的網絡請求,PostInfo就是我們剛剛定義的實體類。參數中也使用了註解@Query,用於拼接傳入的字段(type=yuantong&postid=11111111111)。

網絡請求:

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://www.kuaidi100.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

RetrofitService service = retrofit.create(RetrofitService.class);
Call<PostInfo> call = service.getPostInfo("yuantong", "11111111111");
call.enqueue(new Callback<PostInfo>() {
    @Override
    public void onResponse(Call<PostInfo> call, Response<PostInfo> response) {
        Log.i("http返回:", response.body().toString() + "");
    }

    @Override
    public void onFailure(Call<PostInfo> call, Throwable t) {

    }
});

可以看到Retrofit使用了Builder模式,首先傳入baseUrl,由於返回的數據是json類型的,還需要添加轉換工廠類,這需要在build.gradle文件中加入依賴:

compile 'com.squareup.retrofit2:converter-gson:2.3.0'

然後調用Retrofit的create方法創建RetrofitService的實體類,得到實體類之後就可以調用其中的getPostInfo方法並傳入參數,getPostInfo方法會返回一個Call實體類,接着調用Call的enqueue方法,傳入Callback回調,重寫onResponse(請求成功回調)和onFailure(請求失敗回調)方法,response參數中包含了請求結果中的所有信息(body、code、headers等)。

OK,到這裏Retrofit的基本用法就講完了,接下來我們來了解一下Retrofit的其他用法。

2.Retrofit更多用法

請求方法

在RetrofitService的getPostInfo方法中,我們使用了@GET註解,說明這是一個GET方法,當然也可以寫成HTTP協議中的其他請求方法(比如POST、PUT、DELETE、HEAD等)。

請求參數

在getPostInfo方法的參數中使用了@Query註解,除此之外還可以使用@QueryMap、@Path、@Body、@FormUrlEncoded/@Field、@Multipart/@Part、@Header/@Headers。

  • @Query()
@GET("query")
Call<PostInfo> getPostInfo(@Query("type") String type, @Query("postid") String postid);

相當於

@GET(query?type=type&postid=postid)
Call<PostInfo> getPostInfo(@Query("type") String type, @Query("postid") String postid);
  • @QueryMap

當參數很多的時候可以使用Map集合:

@GET("query")
Call<Book> getSearchBook(@QueryMap Map<String, String> parameters);
  • @Path

用於替換url中的某些字段,當url中字段不確定時可以使用:

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);

id可以爲任意字段,需要和@Path(“id”)中的字段保持一致,如果需要請求參數,也可以使用@Query拼接:

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
  • @Body

可以使用實體類作爲請求體,Retrofit會幫我們自動轉換:

@POST("users/new")
Call<User> createUser(@Body User user);
  • @FormUrlEncoded/@Field

用於傳送表單數據,注意在頭部需要加上@FormUrlEncoded,first_name代表key,first代表value:

@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
  • @Multipart/@Part

用於上傳文件:

@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
  • @Header/@Headers

用於設置請求頭:

@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

也可以通過@Headers設置:

@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();
@Headers({
    "Accept: application/vnd.github.v3.full+json",
    "User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);

轉換器

Retrofit支持的序列化庫:

  • Gson: com.squareup.retrofit2:converter-gson

  • Jackson: com.squareup.retrofit2:converter-jackson

  • Moshi: com.squareup.retrofit2:converter-moshi

  • Protobuf: com.squareup.retrofit2:converter-protobuf

  • Wire: com.squareup.retrofit2:converter-wire

  • Simple XML: com.squareup.retrofit2:converter-simplexml

  • Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

3.Retrofit + RxJava結合使用

如果你對RxJava還不太瞭解,可以看下這篇文章《給 Android 開發者的 RxJava 詳解》

首先在build.gradle文件中加入依賴:

compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
compile 'io.reactivex:rxandroid:1.2.1'

將RetrofitService類中getPostInfo方法的返回值修改爲Observable(被觀察者):

public interface RetrofitService {

    /**
     * 獲取快遞信息
     * Rx方式
     *
     * @param type   快遞類型
     * @param postid 快遞單號
     * @return Observable<PostInfo>
     */
    @GET("query")
    Observable<PostInfo> getPostInfoRx(@Query("type") String type, @Query("postid") String postid);
}

在創建Retrofit時添加RxJava支持:

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://www.kuaidi100.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava
        .build();

獲取被觀察者:

RetrofitService service = retrofit.create(RetrofitService.class);
Observable<PostInfo> observable = service.getPostInfoRx("yuantong", "11111111111");

訂閱:

observable.subscribeOn(Schedulers.io()) // 在子線程中進行Http訪問
        .observeOn(AndroidSchedulers.mainThread()) // UI線程處理返回接口
        .subscribe(new Observer<PostInfo>() { // 訂閱

            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(PostInfo postInfo) {
                Log.i("http返回:", postInfo.toString() + "");
            }
        });

在RxJava中,由於鏈式調用的影響,是被觀察者訂閱觀察者。

到這裏Retrofit + RxJava結合使用就講完了,由於Retrofit、RxJava屬於同門師兄弟,結合使用還是很容易的。

4.Retrofit打印請求參數

Retrofit中無法打印請求參數,由於Retrofit是基於OkHttp進行封裝的,可以對OkHttp添加日誌攔截器來打印請求參數:

在build.gradle文件中加入依賴:

compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'

OkHttp添加攔截器:

public class RetrofitUtils {

    /**
     * 獲取OkHttpClient
     * 用於打印請求參數
     *
     * @return OkHttpClient
     */
    public static OkHttpClient getOkHttpClient() {
        // 日誌顯示級別
        HttpLoggingInterceptor.Level level = HttpLoggingInterceptor.Level.BODY;
        // 新建log攔截器
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                Log.i("Http請求參數:", message);
            }
        });
        loggingInterceptor.setLevel(level);
        // 定製OkHttp
        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
        // OkHttp進行添加攔截器loggingInterceptor
        httpClientBuilder.addInterceptor(loggingInterceptor);
        return httpClientBuilder.build();
    }
}

將定製的OkHttpClient添加到Retrofit中:

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(Constant.SERVER_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .client(RetrofitUtils.getOkHttpClient()) // 打印請求參數
        .build();

大功告成!

5.寫在最後

源碼已託管到GitHub上,歡迎Fork,覺得還不錯就Start一下吧!

GitHub傳送門

點擊下載源碼

歡迎同學們吐槽評論,如果你覺得本篇博客對你有用,那麼就留個言或者頂一下吧(^-^)

在下篇文章中將會探討一下Retrofit封裝的最佳姿勢,敬請期待!

《Android 探討一下Retrofit封裝的最佳姿勢》

已修改爲支持RxJava2,最新代碼已同步至GitHub。

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
發佈了64 篇原創文章 · 獲贊 275 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章