1. 程式人生 > >Retrofit + RxJava+RxAndroid

Retrofit + RxJava+RxAndroid

一、背景

經常看到專案用Retrofit+RxJava+RxAndroid的框架,為了看懂專案的結構。現在來了解一下,Retrofit: Retrofit是Square 公司開發的一款正對Android 網路請求的框架。底層基於OkHttp 實現,OkHttp 已經得到了google 官方的認可OkHttp: 也是Square 開源的網路請求庫

RxJava:RxJava 在 GitHub 主頁上的自我介紹是 “a library for composing asynchronous and event-based programs using observable sequences for the Java VM”(一個在 Java VM 上使用可觀測的序列來組成非同步的、基於事件的程式的庫)。這就是 RxJava ,概括得非常精準。總之就是讓非同步操作變得非常簡單。

各自的職責:Retrofit 負責請求的資料和請求的結果,使用介面的方式呈現,OkHttp 負責請求的過程,RxJava 負責非同步,各種執行緒之間的切換RxJava + Retrofit + okHttp 已成為當前Android 網路請求最流行的方式。

二、Retrofit 寫一個網路請求

1,首先,要使用Retrofit ,你肯定需要把它的包引入,在你的build.gradle檔案中新增如下配置:

compile 'com.squareup.retrofit2:retrofit:2.1.0'//retrofit 
 compile 'com.google.code.gson:gson:2.6.2'
//Gson 庫 //下面兩個是RxJava 和RxAndroid compile 'io.reactivex:rxjava:1.1.0' compile 'io.reactivex:rxandroid:1.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0'//轉換器,請求結果轉換成Model compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'//配合Rxjava 使用

2,建立一個Retrofit 例項,並且完成相關的配置

public static final String BASE_URL = "https://api.douban.com/v2/movie/"
; Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build();
說明:配置了介面的baseUrl和一個converter,GsonConverterFactory 是預設提供的Gson 轉換器,Retrofit 也支援其他的一些轉換器,詳情請看官網

3,建立一個 介面 ,程式碼如下:

public interface MovieService { 

 //獲取豆瓣Top250 榜單 
 @GET("top250")
 Call<MovieSubject> getTop250(@Query("start") int start,@Query("count")int count);

}
說明:定義了一個方法getTop250,使用get請求方式,加上@GET 標籤,標籤後面是這個介面的 尾址top250,完整的地址應該是 baseUrl+尾址 ,引數 使用@Query標籤,如果引數多的話可以用@QueryMap標籤,接收一個Map

4,用Retrofit 建立 介面例項 MoiveService,並且呼叫介面中的方法進行網路請求,程式碼如下:

//獲取介面例項
MovieService MovieService movieService = retrofit.create(MovieService.class); 
//呼叫方法得到一個Call 
Call<MovieSubject> call = movieService.getTop250(0,20);
 //進行網路請求 
call.enqueue(new Callback<MovieSubject>() {
       @Override 
       public void onResponse(Call<MovieSubject> call, Response<MovieSubject> response) { 
            mMovieAdapter.setMovies(response.body().subjects);     
            mMovieAdapter.notifyDataSetChanged(); 
       } 
      @Override 
      public void onFailure(Call<MovieSubject> call, Throwable t) { 
         t.printStackTrace(); 
      } 
});


以上示例是用get方式完成,如果要使用post 方式,我們只需要修改一下介面中的方法定義,如下:

public interface MovieService { 
        //獲取豆瓣Top250 榜單 
       @FormUrlEncoded
       @POST("top250") 
       Call<MovieSubject> getTop250(@Field("start") int start, @Field("count") int count);
}

說明:使用POST 請求方式時,只需要更改方法定義的標籤,用@POST 標籤,引數標籤用 @Field 或者@Body或者FieldMap,注意:使用POST 方式時注意2點,1,必須加上 @FormUrlEncoded標籤,否則會拋異常。2,使用POST方式時,必須要有引數,否則會拋異常, 原始碼拋異常的地方如下:

if (isFormEncoded && !gotField) { 
      throw methodError("Form-encoded method must contain at least one @Field."); 
}

以上就是一個使用Retrofit 完成一個網路請求的完整示例,其他標籤使用方式請看官網Retrofit官網,官網用法也介紹的比較詳細,此外,發現了一篇部落格也介紹得比較詳細,Retrofit用法詳解

三,配合RxJava 使用

1, 更改定義的介面,返回值不再是一個Call ,而是返回的一個Observble.

public interface MovieService { 
    //獲取豆瓣Top250 榜單  
    @GET("top250") 
    Observable<MovieSubject> getTop250(@Query("start") int start, @Query("count")int count);
 }

2,建立Retrofit 的時候新增如下程式碼

addCallAdapterFactory(RxJavaCallAdapterFactory.create())

3,新增轉換器Converter(將json 轉為JavaBean)

addConverterFactory(GsonConverterFactory.create())

4,Activity 或者 Fragment 中傳入 Subscriber 建立訂閱關係

Subscription subscription = movieService.getTop250(0,20) 
.subscribeOn(Schedulers.io()) 
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<MovieSubject>() { 
@Override
 public void onCompleted() { 

 } 
@Override 
public void onError(Throwable e) { 

} 
@Override
 public void onNext(MovieSubject movieSubject) { 
        mMovieAdapter.setMovies(movieSubject.subjects); 
        mMovieAdapter.notifyDataSetChanged(); 
   } 
});
以上是加入RxJava 後的網路請求,返回不再是一個Call ,而是一個Observable, 在Activity / Fragment 中傳入一個Subscriber 建立訂閱關係,就可以在 onNext 中處理結果了,RxJava 的好處是幫我處理執行緒之間的切換,我們可以在指定訂閱的在哪個執行緒,觀察在哪個執行緒。我們可以通過操作符進行資料變換。整個過程都是鏈式的,簡化邏輯。其中FlatMap 操作符 還可以解除多層巢狀的問題。總之,RxJava 很強大,能幫我處理很多複雜的場景,如果熟練使用的話,那麼能提升我們的開發效率。