Retrofit + RxJava + OkHttp 讓網路請求變的簡單-基礎篇

yangxi_001發表於2017-05-17

最近因為手頭上的工作做完了,比較閒,想著做一些優化。看到以前用的那一套網路框架新增一個請求比較麻煩,並且比較難用,所以想改造一下網路框架。現在Android 市面上很火的當然是 Retrofit+RxJava + OkHttp, 功能強大,簡單易用,因此選用這套方案來改造網路庫。本篇文章是對Retrofit 的基本使用方法做一些簡單的介紹。後面會再寫一篇 Retrofit + RxJava + OkHttp 的封裝過程。以下是正文。

簡介:

Retrofit: Retrofit是Square 公司開發的一款正對Android 網路請求的框架。底層基於OkHttp 實現,OkHttp 已經得到了google 官方的認可。Retrofit官網

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 寫一個網路請求

以獲取豆瓣 Top250 榜單為例,地址:https://api.douban.com/v2/movie/

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 也支援其他的一些轉換器,詳情請看官網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(); 
      } 
});

以上是非同步方式請求,還有同步方式execute(),返回一個Response,程式碼如下:

Response<MovieSubject> response = call.execute();

以上就是用Retrofit 完成了一個網路請求,獲取豆瓣top250 榜單電影,效果圖如下:


84193B9F-BBAE-4967-ADB4-F923A422AD64.png

以上示例是用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 很強大,能幫我處理很多複雜的場景,如果熟練使用的話,那麼能提升我們的開發效率。這裡不打算講RxJava 的內容,如果還不瞭解RxJava ,或者還對RxJava不熟悉的話,推薦幾篇寫很優秀的部落格。

1,RxJava 的經典文章,扔物線的 給 Android 開發者的 RxJava 詳解
2,關於RxJava 友好的文章
3,關於RxJava 友好的文章-進階

三,加入 OkHttp 配置

通過OkHttpClient 可以配置很多東西,比如連結超時時間,快取,攔截器等等。程式碼如下:

// 建立 OKHttpClient 
OkHttpClient.Builder builder = new OkHttpClient.Builder(); 
     builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//連線超時時間 
     builder.writeTimeout(DEFAULT_TIME_OUT,TimeUnit.SECONDS);//寫操作 超時時間 
     builder.readTimeout(DEFAULT_TIME_OUT,TimeUnit.SECONDS);//讀操作超時時間 

  // 新增公共引數攔截器 
BasicParamsInterceptor basicParamsInterceptor = new BasicParamsInterceptor.Builder() 
    .addHeaderParam("userName","")//新增公共引數 
    .addHeaderParam("device","") 
    .build(); 

 builder.addInterceptor(basicParamsInterceptor); 

// 建立Retrofit
 mRetrofit = new Retrofit.Builder() 
     .client(builder.build()) 
     .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
     .addConverterFactory(GsonConverterFactory.create()) 
     .baseUrl(ApiConfig.BASE_URL) 
     .build();

以上只是配置了一些簡單的項,如,連線超時時間,實際專案中,我們可能有一些公共的引數,如 ,裝置資訊,渠道,Token 之類的,每個介面都需要用,我們可以寫一個攔截器,然後配置到OKHttpClient裡,通過 builder.addInterceptor(basicParamsInterceptor) 新增,這樣我們就不用每個介面都新增這些引數了。快取也可以通過寫一個攔截器來實現(後面文章再講)。

以上就是Retrofit+RxJava+OkHttp實現網路請求的簡單演示,如果每個介面都這麼寫的話,程式碼量太多,而且不優雅。所以還需要我們封裝一下,由於篇幅有限,封裝放到下一篇文章。

Retrofit + RxJava + OkHttp 封裝已更新,請看Retrofit + RxJava + OkHttp 讓網路請求變的簡單-封裝篇

參考部落格:
1,Retrofit用法詳解
2,基於Retrofit、OkHttp、Gson封裝通用網路框架
3,RxJava 與 Retrofit 結合的最佳實踐

轉自:http://www.jianshu.com/p/5bc866b9cbb9#

相關文章