为什么要用Volley中的RequestFuture封装RxJava来用异步请求处理同步请求?

摘要:
几天前,健哥让我学习RvJava,当它用于网络请求时,它更加简洁和有条理,然后他会花时间做研究。现在项目中的网络库是Volley。结合项目和在线演示,这个问题突然出现在我的脑海中。现在看来有点傻了。首先,解释名词。Volley是谷歌的父亲为我们封装的网络请求库。它帮助我们封装特定的请求、线程切换和数据转换。它适用于短的、多并发的网络请求。Volley主要使用两个类:RequestQueue和Request。

前几天健哥喊我研究一下RvJava,在网络请求用,更简洁更有条理,然后就会抽空研究研究,现在项目里网络库是Volley,就结合项目和网上的demo看,突然脑袋蹦出这个问题,现在看起来这个问题有一点蠢蠢的。

firstly,名词解释一下。

Volley是谷歌爸爸给咱们封装好了的网络请求库,帮我们封装了具体的请求,线程切换以及数据转换,适合短小多并发的网络请求。

Volley要主要用到的两个类:RequestQueueRequest

两个最基础的Request实现JsonObjectRequest和StringRequest,都是请求的作用,用以请求的“信物“”不同而已,所有的HTTP请求都是由这个类创建的,它封装了用于HTTP请求的主要参数。(这是异步网络请求,所以有Response Listener,Error Listener的回调)

  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。

(同步请求就是,打个比方喊你过来,你不过来,我就一直喊,不走了(线程阻塞在那),直到你过来,调用OnResponse,你要是超过我设定的时间一直不过来,我就调用OnError;异步请求就是,我喊了一声让你过来,然后我就走了,至于啥时候过来我就不管了,你过来了,我就回调onResponse ,你不过来,我就回调onError)

RequestFuture工作原理:

  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 :借用扔物线的话

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); } });

免责声明:文章转载自《为什么要用Volley中的RequestFuture封装RxJava来用异步请求处理同步请求?》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇nginx配置反向代理解决跨域防火墙识别、负载均衡识别、waf识别下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

spring5 源码深度解析----- AOP的使用及AOP自定义标签

我们知道在面向对象OOP编程存在一些弊端,当需要为多个不具有继承关系的对象引入同一个公共行为时,例如日志,安全检测等,我们只有在每个对象里引入公共行为,这样程序中就产生了大量的重复代码,所以有了面向对象编程的补充,面向切面编程(AOP),AOP所关注的方向是横向的,不同于OOP的纵向。接下来我们就详细分析下spring中的AOP。首先我们从动态AOP的使用...

C#Win32API编程之PostMessage

  由于C#屏蔽了很多操作系统内核级的操作,将保护机制进行了加强,通过普通方法是无法完成如后台键鼠模拟、进程内存读写、网络封包拦截等操作的。   而C#又提供了调用非托管代码的DllImport,使得我们可以调用操作系统较为底层的API来完善程序功能。   本文就C#调用Win32API函数PostMessage完成指定窗体后台键鼠模拟作为示例,粗略讲解一...

IO与线程状态

这几天在看IO和NIO, 说IO是阻塞的,当多个IO访问服务器时,发生阻塞的时候,CPU要不停的轮询每个IO的线程,看哪个IO的阻塞解除。会浪费CPU资源。 然后我看了线程的状态分类,专门有人说过阻塞和同步是不一样的。 1、新建状态(New):新创建了一个线程对象。 2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法...

额!Java中用户线程和守护线程区别这么大?

在 Java 语言中线程分为两类:用户线程和守护线程,而二者之间的区别却鲜有人知,所以本文磊哥带你来看二者之间的区别,以及守护线程需要注意的一些事项。 1.默认用户线程 Java 语言中无论是线程还是线程池,默认都是用户线程,因此用户线程也被成为普通线程。 以线程为例,想要查看线程是否为守护线程只需通过调用 isDaemon() 方法查询即可,如果查询的值...

ManualResetEvent的理解

首先弄清楚, ManualResetEvent 是WaitEventHandler(等待事件句柄)的一个子类。ManualResetEvent 允许线程通过发信号互相通信。通常,此通信涉及一个线程在其他线程进行之前必须完成的任务。可以通过将布尔值传递给构造函数来控制 ManualResetEvent 的初始状态,如果初始状态处于终止状态,为 true;否则...

浅析.Net下的多线程编程(1)

作者:peter 出处:天极论坛 多线程是许多操作系统所具有的特性,它能大大提高程序的运行效率,所以多线程编程技术为编程者广泛关注。 目前微软的.Net战略正进一步推进,各种相关的技术正为广大编程者所接受,同样在.Net中多线程编程技术具有相当重要的地位。本文我就向大家介绍在.Net下进行多线程编程的基本方法和步骤。 开始新线程 在.Net下创建一个新线...