爲何要用Volley中的RequestFuture封裝RxJava來用異步請求處理同步請求?

前幾天健哥喊我研究一下RvJava,在網絡請求用,更簡潔更有條理,而後就會抽空研究研究,如今項目裏網絡庫是Volley,就結合項目和網上的demo看,忽然腦殼蹦出這個問題,如今看起來這個問題有一點蠢蠢的。git

firstly,名詞解釋一下。github

 

Volley是谷歌爸爸給我們封裝好了的網絡請求庫,幫咱們封裝了具體的請求,線程切換以及數據轉換,適合短小多併發的網絡請求。網絡

Volley要主要用到的兩個類:RequestQueueRequest併發

兩個最基礎的Request實現JsonObjectRequest和StringRequest,都是請求的做用,用以請求的「信物「」不一樣而已,全部的HTTP請求都是由這個類建立的,它封裝了用於HTTP請求的主要參數。(這是異步網絡請求,因此有Response Listener,Error Listener的回調)app

  1. METHOD Type – GET, POST, PUT, DELETE
  2. URL
  3. Request data (HTTP Body)
  4. Successful Response Listener
  5. Error Listener

RequsetQueue:這是一個分發隊列,用來取Requst並在工做線程中執行,若是cache中找到就從cache中獲取response,沒有就獲取,而後將結果回傳到UI線程。異步

然而·Volley做爲優秀的網絡請求庫,是也能夠完成同步網絡請求,須要用到的類: RequestFuture。async

(同步請求就是,打個比方喊你過來,你不過來,我就一直喊,不走了(線程阻塞在那),直到你過來,調用OnResponse,你要是超過我設定的時間一直不過來,我就調用OnError;異步請求就是,我喊了一聲讓你過來,而後我就走了,至於啥時候過來我就無論了,你過來了,我就回調onResponse ,你不過來,我就回調onError)ide

RequestFuture工做原理:post

  1. 構造RequestFuture:RequestFuture<JSONObject> future = RequestFuture.newFuture();
  2. 構造volley請求的時候,將上面的對象傳入請求中;JSONObjectRequest request=JSONObjectRequest(Request.Method.GET, Url,future,future,....);
  3. 將請求加入請求隊列:    RequestManager.getRequestQueue().add(request);
  4. 隨後調用RequestFuture.get方法,該方法會在當前線程阻塞
  5. get方法內部調用wait(time),在等待時間內尚未結果這拋出超時異常;(wait(0)是無限期等待)
  6. 在get的wait過程當中,若是volley請求到來了,則會調用RequestFuture的onResponse方法,設置該對象中的private T mResult;  RequestFuture.get()會返回結果,同時調用notifyall(),喚醒等待中的線程,不在阻塞。
  7. 注意,由於該方法是會阻塞的,所以千萬不要在UI線程中調用get方法!!所以須要在一個新線程中進行阻塞,這個交給RxJava實現吧。

 

 

RxJava :借用扔物線的話url

RxJava 究竟是什麼

一個詞:異步

RxJava 在 GitHub 主頁上的自我介紹是 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一個在 Java VM 上使用可觀測的序列來組成異步的、基於事件的程序的庫)。這就是 RxJava ,歸納得很是精準。

然而,對於初學者來講,這太難看懂了。由於它是一個『總結』,而初學者更須要一個『引言』。

其實, RxJava 的本質能夠壓縮爲異步這一個詞。說到根上,它就是一個實現異步操做的庫,而別的定語都是基於這之上的。

RxJava 好在哪

換句話說,『一樣是作異步,爲何人們用它,而不用現成的 AsyncTask / Handler / XXX / ... ?』

一個詞:簡潔

異步操做很關鍵的一點是程序的簡潔性,由於在調度過程比較複雜的狀況下,異步代碼常常會既難寫也難被讀懂。 Android 創造的 AsyncTask 和Handler ,其實都是爲了讓異步代碼更加簡潔。RxJava 的優點也是簡潔,但它的簡潔的不同凡響之處在於,隨着程序邏輯變得愈來愈複雜,它依然可以保持簡潔。

這是RxJava特性,具體移步  http://gank.io/post/560e15be2dca930e00da1083


好了,名詞解釋就到這。下面來回答問題,爲何要用Volley中的RequestFuture封裝RxJava來用異步請求處理同步請求?

換一種思考,爲何不用Volley中的RequestFuture封裝RxJava來用異步請求處理異步請求?聽起來更蠢對不對,異步,開一個線程,異步處理再開一個線程,這樣就開了兩個線程,很浪費對不對。

爲何不用Volley中的RequestFuture封裝RxJava來用同步請求異步處理請求?RxJava也能夠實現同步的,觀察者被觀察者放一個線程裏頭。以前用Volley都是異步請求,就實現了咱們想要的功能,爲何還要使用RxJava,還給同步了?咱們用RxJava由於它的異步+有條理,物盡其用呀。

這個算反證法吧,因此咱們用Volley中的RequestFuture封裝RxJava來用異步請求處理同步請求。

 

RxJava+Volley

public class RxRequest {

    /**
     * 發送post請求
     *
     * @param url
     * @param target
     * @param <T>
     * @return
     */
    public static <T> Observable<T> post(String url, Class<?> target) {
        return request(url, target, Request.Method.POST, new DefaultRetryPolicy());
    }

    /**
     * 發送post請求
     *
     * @param url
     * @param target
     * @param <T>
     * @return
     */
    public static <T> Observable<T> post(String url, Class<?> target, RetryPolicy retryPolicy) {
        return request(url, target, Request.Method.POST, retryPolicy);
    }

    /**
     * 發送Get請求
     *
     * @param url
     * @param target
     * @param <T>
     * @return
     */
    public static <T> Observable<T> get(String url, Class<?> target) {
        return request(url, target, Request.Method.GET, new DefaultRetryPolicy());
    }

    /**
     * 發送Get請求
     *
     * @param url
     * @param target
     * @param <T>
     * @return
     */
    public static <T> Observable<T> get(String url, Class<?> target, RetryPolicy retryPolicy) {
        return request(url, target, Request.Method.GET, retryPolicy);
    }

    public static <T> Observable<T> request(String url, Class<?> target, int method, RetryPolicy retryPolicy) {

        final RequestFuture<T> requestFuture = RequestFuture.newFuture();

        final GsonRequest<T> request = new GsonRequest<T>(target, method, url, null, requestFuture, requestFuture);
        request.setRetryPolicy(retryPolicy);
        request.setTag(url);

        requestFuture.setRequest(request);//這是爲了下面的requestFuture.isCancelled

        return Observable.create(new Observable.OnSubscribe<T>() {

            @Override
            public void call(Subscriber<? super T> subscriber) {
                try {
                    //只在被訂閱後才進行網絡請求處理
                    RequestManager.getRequestQueue().add(request);
                    if (!subscriber.isUnsubscribed() && !requestFuture.isCancelled()) {
                        subscriber.onNext(requestFuture.get());//阻塞,返回結果,喚醒
                        subscriber.onCompleted();
                    }
                } catch (Exception e) {
                    subscriber.onError(e);
                }
            }

        }).subscribeOn(Schedulers.io());//開io線程,網絡請求
    }

    /**
     * 取消請求
     *
     * @param url
     */
    public static void cancel(final String url) {
        RequestManager.getRequestQueue().cancelAll(new RequestQueue.RequestFilter() {
            @Override
            public boolean apply(Request<?> request) {
                return request.getTag().equals(url);
            }
        });
    }
}

activity(或fragment中)

 RxRequest.<MyModel>post(url, MyModel.class)
            .observeOn(AndroidSchedulers.mainThread())//觀察者在UI線程
            .subscribe(new Subscriber<MyModel>() { @Override public void onCompleted() { Log.i("RxRequest", "onCompleted"); } @Override public void onError(Throwable e) { Log.e("RxRequest", "onError", e); } @Override public void onNext(MyModel myModel) { Log.i("RxRequest", "onNext==>" + myModel); } });
相關文章
相關標籤/搜索