RxJava和Retrofit的簡單使用

在最近作的項目中,由於頻繁用到網絡請求,因此使用瞭如今比較流行的框架RxJava和Retrofit來代替以前的Okhttp的繁瑣請求。java

我這邊寫的比較簡單,本身在小項目中更使用的,若是須要深刻研究,進行一些封裝的,管理RxJava生命週期的,請移步http://p.codekk.com/detail/Android/RuffianZhong/Rx-Mvp。react

retrofit是用來作網絡請求操做,RxJava是用來切換線程、轉換數據操做的。android

首先第一步,使用三方的框架,確定是先添加依賴包。項目中用的Rxjava2.0、retrofit2.0,並且Rxjava2.0和Rxjava1.0並不兼容,因此使用起來須要注意。添加一下依賴。web

compile "com.squareup.retrofit2:retrofit:$rootProject.versions.libRetrofit"
compile "com.squareup.retrofit2:converter-gson:$rootProject.versions.libRetrofit"
compile "com.squareup.retrofit2:adapter-rxjava2:$rootProject.versions.libRetrofit"
compile "com.squareup.okhttp3:okhttp:$rootProject.versions.libOkhttp"
compile "com.squareup.okhttp3:logging-interceptor:$rootProject.versions.libOkhttp"
compile "io.reactivex.rxjava2:rxjava:$rootProject.versions.libRxJava"
compile "io.reactivex.rxjava2:rxandroid:$rootProject.versions.libRxAndroid"

第二步,建立一個Api實例  用來獲取接口的請求對象    在init()方法中經過baseUrl或獲得Retrofit對象,  請求方法等都是放在接口中,接口與retrofit關聯在getNetDemo()方法中實現。cookie

 

public class NetDemoApi {
private static NetDemoApi nInstance = new NetDemoApi();
private Retrofit mRequestDemo;
//baseUrl是每個網絡請求的前段,但必須是以 「/」結尾
private String mRequestDemoBaseUrl = "www.baidu.com/";
public static NetDemoApi getInstance(){
return nInstance;
}
private NetDemoApi(){
init();
}

private void init() {
//這一步就把baseurlRetrofit關聯了起來,生成Retrofit對象
mRequestDemo = configure(mRequestDemoBaseUrl);
}

private NetDemo getNetDemo(){
return mRequestDemo.create(NetDemo.class);
}

//配置retrofit
private Retrofit configure(String baseUrl){
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
WLog.i(message);
}
});
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
//這隻網絡請求的攔截器 若是須要獲取到響應頭等相應信息,在此處就能夠得到 若是不須要能夠不寫
builder.networkInterceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
Headers headers = response.headers();
List<String> cookies = headers.values("Set-Cookie");
Session session = Session.getInstance();
session.setCookies(Utils.getCookie(cookies));
Log.d(getClass().getSimpleName(),"設置cookie " + session.getCookies());
return response;
}
});
builder.addInterceptor(logging);
builder.connectTimeout(30, TimeUnit.SECONDS);
builder.readTimeout(40, TimeUnit.SECONDS);
OkHttpClient client = builder.build();
return new Retrofit.Builder()
.baseUrl(baseUrl)
.client(client)
//這是rxjava的轉換器,這個是rxjava2的默認適配器工廠,若是咱們須要轉換成bean,能夠添加gson的轉換器,直接添加就能夠,須要添加依賴包
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
}

第三步,寫實現的接口,這個接口中,纔是咱們須要請求的路徑  以下   @get 就是一個get請求的方法,     @post就是一個post請求
網絡

@url  是直接傳入一個已知的URl進去,直接請求Url,並且跟baseUrl無關,不會跟baseUrl進行拼接;session

@Query 就是在URl後面進行鍵值對的拼接,以下  tip傳入1 ,就會把 tip=1 拼接到loginicon=true的後面,get和post請求都是這樣拼接。app

@Path 就是把傳入的字符串直接傳入註解中{uuid}中的位置處;框架

@body 是post請求時,傳入的requestBody對象;ide

@Header  能夠給網絡請求添加請求頭信息,添加Cookie就寫cookie,@Header("Cookie") String cookie,

以上傳入的url參數都會和baseUrl進行拼接,獲得一個完整的Url去進行網絡請求(除了@url)。

返回的就是Observable對象,咱們調用此方法後,得到observable對象,接下來用Rxjava進行數據解析,篩選。

public interface NetDemo {
@GET
Observable<ResponseBody> requestDemo(@url String url);
   
  @GET("cgi-bin/mmwebwx-bin/login?loginicon=true")
  Observable<ResponseBody> requestScanResult(@Query("tip") int tip,
  @Query("uuid") String uuid,
  @Query("r") String r,
  @Query("_") String p);

  @POST("qrcode/{uuid}")
  Observable<ResponseBody> requestGenQRCode(@Path("uuid") String uuid,
  @Body RequestBody body);
  @POST("cgi-bin/mmwebwx-bin/webwxstatusnotify?lang=zh_CN")
  public Observable<ResponseBody> webwxstatusnotify(@Query("pass_ticket") String passTicket,
   @Header("Cookie") String cookie,
   @Body RequestBody body);

}

第四步,在代碼中進行網絡請求,

 

Observable<ResponseBody> observable = WeChatNetApi.getInstance().getLoginInfo().requestLoginInfo(url);      //返回Observable對象
observable.subscribeOn(Schedulers.io())                                           //進行網絡請求是在那個線程 io 就是在子線程
     .map(new Function<ResponseBody, Bitmap>() {                                 //能夠經過map進行轉換,把結果轉換爲一個咱們須要使用的類型(如demo,返回一個bitmap類型)
    @Override
     public Bitmap apply(@io.reactivex.annotations.NonNull
   ResponseBody responseBody) {
   return BitmapFactory.decodeStream(responseBody.byteStream());
      }
    })
    .flatMap(new Function<String, ObservableSource<Bitmap>>() {                         //還能夠經過flatMap轉化爲Observable對象,轉換爲Observable對象後,還能夠繼續進行轉換操做,直到咱們須要的類型
     @Override
     public ObservableSource<Bitmap> apply(
     @io.reactivex.annotations.NonNull String uuid) {
     return genQRCode(uuid);
     }
    }
   
.filter(new Func1<Community, Boolean>() {                                     //只有返回true,纔會繼續向下走,若是返回是false,就不會繼續向下走
      @Override
      public Boolean call(Community community) {
        return community.houses.size()>10;
       }
     })
 .observeOn(AndroidSchedulers.mainThread())                                    //網絡請求結束,切換回主線程,進行數據處理,或者顯示的操做
    .subscribe(new Observer<ResponseBody>() {                                  //轉換結束,獲得了咱們須要的數據,進行顯示,先切換到主線程
    @Override
     public void onSubscribe(Disposable d) {
      
     }
    @Override
    public void onNext(ResponseBody body) {                                 //訂閱後subscribe會執行的方法
     messageActivity.returnTextInfo(asJsonObject, l);
     }
    @Override
    public void onError(Throwable e) {                                    //若是流程中有報錯,會走到此

    }
    @Override
    public void onComplete() {                                         //onNext以後,若是還有後續的動做,能夠在此繼續,onnext後會調用complete;

    }
    });



.doOnNext(new Consumer<ResponseBody>() {                                   //doOnNext 直接訂閱是一個偷懶的寫法,這樣寫代碼比較簡潔,並且這一步操做完以後,我也不須要繼續任何操做
@Override
public void accept(@io.reactivex.annotations.NonNull ResponseBody body) throws Exception {
handleLoginInfoResponse(url,body); } }).subscribe();
相關文章
相關標籤/搜索