1. 程式人生 > >Retrofit和RxJava結合使用

Retrofit和RxJava結合使用

使用Retrofit的時候就不得不提到RxJava,RxJava是一個基於觀察者模式的非同步實現。關於RxJava的入門學習,強烈推薦《給Android開發者的RxJava詳解》

正如上篇部落格所說,得益於Retrofit中靈活的Converter,所以Retrofit對RxJava的支援也是異常的方便。我個人的感覺是,雖然RxJava的學習曲線比較陡峭,但是一旦學會,程式設計效率將大大提高。如果使用Retrofit而不用RxJava是非常可惜的,本文將闡述如何將Retrofit和RxJava進行結合。。

新增依賴

首先在build.gradle中加入依賴。為了使用gson解析json,還需要加入gson

converter-gson兩個依賴,為了支援RxJava,還需要加入rxjavarxandroid的庫,而銜接RxJava和Retrofit的就是adapter-rxjava這個庫。

compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.google.code.gson:gson:2.7'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'io.reactivex:rxandroid:1.2.0'
compile 'io.reactivex:rxjava:1.1.5'

定義請求介面

和之前的定義一樣,為了使用RxJava,需要把返回值改成Observable型別即可:

public interface RetrofitImageUploadService {
        @Multipart
        @POST("EntranceGuardes/app/appOpen_pushdDataToApp.action")
        Observable<UploadJsonResult> upload(@Part("userId") RequestBody description,
                                            @Part
MultipartBody.Part file); }

這樣,upload方法的返回值就是Observable<UploadJsonResult>型別,可以想象到,這樣的返回值很容易和RxJava的資料流結合起來。

新增adapter-rxjava

和新增Gson支援一樣,只需要在Retrofit物件中加入addCallAdapterFactory即可。addCallAdapterFactory(RxJavaCallAdapterFactory.create())就可以使用RxJavaCallAdapterFactory把Retrofit和RxJava結合起來。

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://172.18.81.155:8080/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

RetrofitImageUploadService service = retrofit.create(RetrofitImageUploadService.class);

進行網路請求

這時呼叫service的upload方法,返回的結果就是Observable<UploadJsonResult>,這樣就很容易與RxJava中豐富的運算子結合起來,方便各種處理。

Observable<UploadJsonResult> r=service.upload(description, body)

使用RxJava運算子

從上一步得到了Observable型別的物件,我們如果需要對返回結果進行一些處理,只需要使用RxJava中的豐富的運算子就可以了。而RxJava中有對lambda表示式的支援,只要使用Java SE8就可以使用lambda表示式來簡寫其中的運算子。

service.upload(description, body)
                .doOnNext(uploadJsonResult -> Log.d("upload image", uploadJsonResult.getMessage()))
                .doOnError(throwable -> Log.d("upload image", "upload failed"));

上面兩句運算子使用了lambda表示式。doOnNext表示如果請求成功,將在日誌中打印出uploadJsonResult.getMessage()中得到的資料。doOnError表示如果請求失敗,將在日誌中列印”upload failed”。除此之外,我們還可以增加執行緒的切換,比如使用observeOn(Schedulers)讓網路請求在io執行緒中執行。

完整程式碼

public class UpLoadImage {
    public interface RetrofitImageUploadService {
        @Multipart
        @POST("EntranceGuardes/app/appOpen_pushdDataToApp.action")
        Observable<UploadJsonResult> upload(@Part("userId") RequestBody description,
                                            @Part MultipartBody.Part file);
    }

    private String imagePath;
    private String userId;

    public UpLoadImage(String userId, String imagePath) {
        this.imagePath = imagePath;
        this.userId = userId;
    }

    public Observable<UploadJsonResult> upload() {
        File file = new File(imagePath);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://172.18.81.155:8080/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

        RetrofitImageUploadService service = retrofit.create(RetrofitImageUploadService.class);


        RequestBody requestFile = RequestBody.create(MediaType.parse("image/*"), file);
        MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile);

        RequestBody description = RequestBody.create(MediaType.parse("text/plain"), userId);

        return service.upload(description, body)
                .doOnNext(uploadJsonResult -> Log.d("upload image", uploadJsonResult.getMessage()))
                .doOnError(throwable -> Log.d("upload image", "upload failed"));

    }
}

程式碼地址