RxJava2.x 创建操作符之 from


题图:Pixabay License

哈喽,朋友们,上一篇文章我们学习了 create & just 操作符,今天我们继续来学习 from 操作符。

from 操作符和 just 操作符一样,也属于创建操作符的一种,from 可将其他种类的对象和数据类型转换为 Observable。

从概念看,just 和 from 是比较相似的,那么,他们两者有什么区别呢?

just 只是简单的原样发射,它会将数组或 Iterable 当做单个数据发射出去,而 from 会将数组或 Iterable 的数据按顺序取出来,然后逐个发射出去,举个例子你就明白了。

举例,我们初始化了一个 list,分别用 just 和 fromIterable 操作符进行处理,并打印了数据的结果。

List<Integer> list = new ArrayList<>();
for (int i = 0; i < 6; i++) {
    list.add(i);
}

Observable.just(list).subscribe((Consumer<List>) list1 -> LogUtil.i(TAG, "just():" + Arrays.toString(list1.toArray())));

Observable.fromIterable(list).subscribe(integer -> LogUtil.i(TAG, "fromIterable():" + integer));

执行结果如下:

I/RxJavaOperatorActivity: just():[0, 1, 2, 3, 4, 5]
I/RxJavaOperatorActivity: fromIterable():0
I/RxJavaOperatorActivity: fromIterable():1
I/RxJavaOperatorActivity: fromIterable():2
I/RxJavaOperatorActivity: fromIterable():3
I/RxJavaOperatorActivity: fromIterable():4
I/RxJavaOperatorActivity: fromIterable():5

从上面打印的日志我们可以看到,just 是将整个 list 数据传递下来了,而 fromIterable 是将 list 中的数据遍历并一个一个发射出去,数组也是一样的道理,数组使用 fromArray 操作符。

这里需要注意一个点,just 是可以接收 1-10 参数的,如果传入 1-5 的数字作为参数,那么它也会按顺序去打印的,而不是作为一个数组发射出去。

举个例子你就明白了:

Observable.just(1, 2, 3, 4, 5).subscribe(integer -> LogUtil.i(TAG, "just():" + integer));

执行结果如下:

I/RxJavaOperatorActivity: just():1
I/RxJavaOperatorActivity: just():2
I/RxJavaOperatorActivity: just():3
I/RxJavaOperatorActivity: just():4
I/RxJavaOperatorActivity: just():5

怎么样?是不是瞬间就懂了。

另外,from 还有一个 fromFuture 操作符,Future 是什么东西?fromFuture 又是如何使用的呢?这个问题问的好,大飞这就给你细细道来。

Future 是 java.util.concurrent 包下的一个接口,我们都知道,创建线程的 2 种方式,一种是直接继承 Thread,另外一种就是实现 Runnable接口,但是这 2 种方式都有一个缺点就是在执行完任务之后无法获取执行的结果。

如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。而自从 JDK 1.5 开始,给我们提供了 Callable 和 Future 接口,通过这两个接口我们可以在任务执行完毕之后得到线程执行的结果。

一般来说,Callable 需要和 ExecutorService 配合来使用的,举个非常简单的例子吧。

    static class MyCallable implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            LogUtil.i(TAG, "call():在这里模拟一些耗时操作...");
            Thread.sleep(3000);
            int sum = 0;
            for (int i = 0; i <= 100; i++) {
                sum += i;
            }
            return sum;
        }
    }

    private void calculate() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<Integer> future = executorService.submit(new MyCallable());

        try {
            LogUtil.i(TAG, "任务运行的结果:" + future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

上面的代码也比较简单,我相信大家都能看得懂,我们的 MyCallable 类实现了 Callable 接口,在 call 方法中进行了一些耗时的操作,然后将结果返回出去,紧接着我们创建了一个线程池,创建了一个 MyCallable 的对象并将其提交到线程池中,最后将执行的结果打印出来。

执行结果如下:

2019-05-19 16:22:36.932 I/RxJavaOperatorActivity: call():在这里模拟一些耗时操作...
2019-05-19 16:22:40.933 I/RxJavaOperatorActivity: 任务运行的结果:5050

我们再来看看如何配合 RxJava 来使用,这里使用到了 fromFuture 操作符,其实使用起来非常简单,简单修改一下上面的代码,相信你立刻就秒懂了!

Observable.fromFuture(future).subscribe(s -> LogUtil.i(TAG, "任务运行的结果:" + s));

这里我们就不调用 future 的 get 方法来获取执行的结果了,而是将 future 对象使用 fromFuture 操作符将其作为参数传递进去,当任务执行完成后,我们的观察者就会收到执行完后的结果,说白了就是 RxJava 内部帮你执行了 get 的方法并把结果回调给你了。

总结一下,对于 Future,它会发射 Future.get() 方法返回的单个数据。

细心的你可能已经发现了,fromFuture 还有一个重载方法:

fromFuture(Future<? extends T> future, long timeout, TimeUnit unit);

那第二个参数和第三个参数是什么意思呢?先别急,我们先看下 Future 接口的定义:

public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

看到没有,我们发现原来 get 方法也有一个重载方法,也就是说 fromFuture 3 个参数的方法中后两个参数对应的就是 get 重载方法中的这两个参数。

那么问题来了,这两个参数有什么作用呢?这两参数的意思是,我们可以指定执行任务的时长和时间单位,如果过了指定的时长,Future 还没有返回一个结果,那么这个 Observable 就会发射异常通知并终止。

我们可以测试一下是不是这样的。我们现在指定一个执行任务的时长,我在执行任务的方法中睡了 3 秒,那么这里我就给它设置成 2 秒,这样设置,任务肯定是没有执行完成的,我们看看这个时候会不会和我们猜测的一样会抛异常。

Observable.fromFuture(future, 2, TimeUnit.SECONDS).subscribe(s -> Observable.fromFuture(future, 2, TimeUnit.SECONDS)
                .subscribe(s -> LogUtil.i(TAG, "任务运行的结果:" + s)
                        , throwable -> LogUtil.e(TAG, "onError:" + throwable.getMessage()));

执行结果如下:

I/RxJavaOperatorActivity: call():在这里模拟一些耗时操作...
E/RxJavaOperatorActivity: onError:null

看到没有,果不其然报错了,这样我们就可以在超时的时候做一些处理了。

好了,我们今天的学习目标就算达成了,感觉是不是很简单,很轻松?我们来回顾下今天所学的东西,首先我们学习了 fromIterable 操作符,它与 just 操作符有相似之处,因此我将其与 just 操作符举例说明了他们的区别。

紧接着我们回顾了 Java 中创建线程的相关知识,并学会了将其配合 fromFuture 操作符一起使用,真的是非常方便的。

如果你学会了就赶紧动手去实践一下吧,有数据表明,学习后实践的吸收效果比不实践的效果高几十倍!

今天的内容确实比较轻松和简单,后面我将继续带领大家一起学习新的内容,大家敬请期待吧!

最后,我和大家分享一下我学习的一些经验或者是见解吧。我们再学习的过程中,可能学的很多东西都是点状的,我们要把学习到的东西学会融会贯通,将他们连接成线即学会相互联系,再将线形成面,再形成体,这样我们学到的知识才能形成一个完整的知识体系,不要只见树叶,不见森林,希望大家在学习的过程中,多思考,多总结!

Ps:扫描下面的二维码,关注「IT大飞说」,回复「加群」,拉你进入兄弟战斗群,最后告诉你们一个小秘密,公号对话框回复「装备01」 送你一件珍藏版的打怪装备,战斗力瞬间可增加 80!!!我使用过,效果杠杠滴!从此,我们就可以一起愉快的装逼了!

飞哥带你去装逼,一直装逼到天黑!

更多干货文章请关注我的微信公众号:
扫一扫关注

另外,我还建了一个免费的知识星球,感兴趣的微信扫码即可加入!

image

发布了138 篇原创文章 · 获赞 168 · 访问量 46万+

猜你喜欢

转载自blog.csdn.net/xinpengfei521/article/details/90345212