[译] 开发者(也就是我)与Rx Observable 类的对话 [ Android RxJava2 ] ( 这究竟是什么?) 第五部分

开发者(也就是我)与Rx Observable 类的对话 [ Android RxJava2 ] ( 这究竟是什么?) 第五部分

又是新的一天,是时候学点新东来西来让今天变得酷炫了。前端

你们好,但愿大家都过的不错。这是咱们 RxJava2 Android 系列的第五篇文章 [ part1, part2, part3, part4 ] 。在这篇文章中,咱们会继续研究 Rx Java Android 。java

动机react

动机和我在第一部分 part1 中分享给你们的同样。如今咱们把以前 4 篇学到的东西融会贯通起来。android

介绍:ios

当我在学习 Rx java Android 的某一天,我有幸与一位 Rx Java 的 Observable 类进行了亲切友好的交谈。好消息是 Observable 类很厚道,令我惊叹不已。我一直觉得 Rx Java 是个大坑逼。他/她不想和开发者作朋友,总给他们穿小鞋。
可是在和 Observable 类谈话之后,我惊喜的发现个人观点是错的。git

我:你好,Observable 类,吃了嘛您?github

Observable 类:你好 Hafiz Waleed Hussain ,我吃过啦。express

我:为啥你的学习曲线这么陡峭?为啥你故意刁难开发者?你这么搞要没朋友了。后端

Observable 类:哈哈,你说的是。我真想交不少朋友,不过我如今也有一些好哥们儿。他们在不一样的论坛上讨论我,介绍我和个人能力。并且这些家伙真的很棒,他们花了好久的时间和我呆在一块儿。只有精诚所至,才会金石为开。但问题是,不少想撩个人人只走肾不走心。他们关注我了一小会就去刷推特脸书,把我给忘了。因此说,对我不真诚的人又如何期望我和他们交朋友呢?数组

我:好吧,若是想和你交朋友的话,我该怎么作?

Observable 类:把注意力集中在我身上,而且坚持足够长的时间,而后你就知道我有多真诚了。

我:嗯,实话实说我不擅长集中精神,可是我擅长无视周围。这样能够嘛?

Observable 类:固然,只要你和我在一块儿的时候能够心无旁骛,我会是你的好朋友的。

我:哇哦,我有种预感,我会和你交上朋友的。

Observable 类:固然,任何人均可以把我当好朋友。

我:如今我有些问题,能够问了嘛?

Observable 类:固然,你能够问成千上万个问题。我会给你答案,可是重要的是须要你本身花时间去思考和吸取。

我:我会的。若是我想把数据转化为 Observable 对象,在 Rx Java 2 Android 里怎么实现?

Observable 类:这个问题的答案很长很长。若是你来看我(Rx Java 2 Observable 类)的源码,你就会发现我一共有12904行代码。(校对 Phoenix 注:在 RxJava 2.0.9 版本。Observable 类已经成功增肥到 13728 行。)

个人团队里也有好几个朋友,能够根据开发者的需求返回 Observable 对象,好比 map ,filter。不过如今我会告诉你几个能够帮助你把任何东西转化为 Observable 对象的方法。抱歉个人回答可能会很长,可是也不会很无聊。我不只仅会演示这些方法如何建立 Observable 对象,同时也会向你展现如何对手头边代码进行重构。

1 just()

经过这个方法,你能够把任意(多个)对象转化成以此对象为泛型的 Observable 对象( Observable )。

String data= "Hello World";
    Observable.just(data).subscribe(s -> System.out.println(s));
Output:
    Hello World复制代码

若是你的数据不止一个,能够像下面那样调用 just 方法 :

String data= "Hello World";
Integer i= 4500;
Boolean b= true;
    Observable.just(data,i,b).subscribe(s -> System.out.println(s));
Output:
    Hello World
    4500
    true复制代码

此 API 最多可接收 10 个数据作参数。

Observable.just(1,2,3,4,5,6,7,8,9,10).subscribe(s -> System.out.print(s+" "));
Output:
    1 2 3 4 5 6 7 8 9 10复制代码

样例代码:(不是个好例子,只是给点提示,告诉你如何在本身的代码中使用)

public static void main(String[] args) {
String username= "username";
String password= "password";
        System.out.println(validate(username, password));
    }

    private static boolean validate(String username, String password) {
boolean isUsernameValid= username!=null && !username.isEmpty() && username.length() > 3;
boolean isPassword= password!=null && !password.isEmpty() && password.length() > 3;
    return isUsernameValid && isPassword;
}复制代码

使用 Observable 类进行重构:

private static boolean isValid= true;
private static boolean validate(String username, String password) {
    Observable.just(username, password).subscribe(s -> {
if (!(s != null && !s.isEmpty() && s.length() > 3))
           throw new RuntimeException();
}, throwable -> isValid= false);
    return isValid;
}复制代码

2 from…

我有一大堆的 API 能够把复杂的数据结构转化为 Observable 对象,好比下面那些以关键字 from 开头的方法:

我想这些 API 从名字就能够看懂它们的意思,因此也不须要更多解释了。不过我会给你一些例子,这样你能够在本身的代码里用的更舒服。

(校对 Phoenix 注:
虽然 fromCallable, fromPublisher, fromFuture 也是 from 开头的方法。可是他们互相之间区别很大。尤为是 fromCallable 和 fromPublisher。)

public static void main(String[] args) {

List<Tasks> tasks= Arrays.asList(new Tasks(1,"description"),
            new Tasks(2,"description"),new Tasks(4,"description"),
            new Tasks(3,"description"),new Tasks(5,"description"));
    Observable.fromIterable(tasks)
            .forEach(task -> System.out.println(task.toString()));
}

private static class Tasks {
    int id;String description;
public Tasks(int id, String description) {this.id= id;this.description = description;}
    @Override
public String toString() {return "Tasks{" + "id=" + id + ", description='" + description + '\'' + '}';}
}
}复制代码

从数组转化为 Observable 对象

public static void main(String[] args) {
Integer[] values= {1,2,3,4,5};
        Observable.fromArray(values)
                .subscribe(v-> System.out.print(v+" "));
    }复制代码

两个例子就够啦,回头你能够亲自试试其余的。

3 create()

你能够把任何东西强行转为 Observable 对象。这个 API 过于强大,因此我的建议使用这个API以前,应该先找找有没有其余的解决方式。大约99%的状况下,你能够用其余的 API 来解决问题。但若是实在找不到,那么就用它也能够。

(校对 Phoenix 注:这里可能做者对 RxJava 2 的 create 还停留在 RxJava 1 的阶段。 RxJava 1.x 确实不推荐 create 方法。而 RxJava 2 的 create 方法是推荐方法。并非 99% 的状况均可以被取代。 RxJava 1.x 的 create 方法现已经成为 RxJava 2.x 的 unsafeCreate ,RxJava 1.2.9 版本也加入了新的安全的 create 重载方法。)

public static void main(String[] args) {
final int a= 3, b = 5, c = 9;
Observable me= Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> observableEmitter) throws Exception {
                observableEmitter.onNext(a);
                observableEmitter.onNext(b);
                observableEmitter.onNext(c);
                observableEmitter.onComplete();
            }
        });
        me.subscribe(i-> System.out.println(i));
    }复制代码

4 range()

这就像是一个 for 循环,就像下面的代码显示的那样。

public static void main(String[] args) {
        Observable.range(1,10)
                .subscribe(i-> System.out.print(i+" "));
    }
Output:
    1 2 3 4 5 6 7 8 9 10复制代码

再来一个例子:

public static void main(String[] args) {

List<String> names= Arrays.asList("Hafiz", "Waleed", "Hussain", "Steve");
for (int i= 0; i < names.size(); i++) {
if(i%2== 0)continue;
        System.out.println(names.get(i));
    }

    Observable.range(0, names.size())
.filter(index->index%2==1)
            .subscribe(index -> System.out.println(names.get(index)));
}复制代码

5 interval()

这个 API 碉堡了。我用两种方法实现同一种需求,你能够比较一下。第一种我用 Java 的线程来实现,另外一种我用 interval() 这个 API ,两种方法会获得同一个结果。

(校对 Phoenix 注:interval() 会默认在 Scheduler.computation() 进行操做。)

public static void main(String[] args) {
    new Thread(() -> {
        try {
            sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        greeting();
    }).start();

    Observable.interval(0,1000, TimeUnit.MILLISECONDS)
            .subscribe(aLong -> greeting());
}

public static void greeting(){
    System.out.println("Hello");
}复制代码

6 timer()

又是一个好的 API。在程序中若是我想一秒钟后调用什么方法,能够用 timer ,就像下面展现的那样:

public static void main(String[] args) throws InterruptedException {
    Observable.timer(1, TimeUnit.SECONDS)
            .subscribe(aLong -> greeting());
    Thread.sleep(2000);
}

public static void greeting(){
    System.out.println("Hello");
}复制代码

7 empty()

这个 API 颇有用,尤为是在有假数据的时候。这个 API 建立的 Observable 对象中,注册的 Observer 对象只调用 complete 方法。好比这个例子,若是在测试运行时发送给我假数据,在生产环境下就调用真的数据。

public static void main(String[] args) throws InterruptedException {
    hey(false).subscribe(o -> System.out.println(o));
}

private static Observable hey(boolean isMock) {
return isMock ? Observable.empty(): Observable.just(1, 2, 3, 4);
}复制代码

8 defer()

这个 API 在不少状况下都会颇有用。我来用下面的例子解释一下:

public static void main(String[] args) throws InterruptedException {
Employee employee= new Employee();
employee.name= "Hafiz";
employee.age= 27;
Observable observable= employee.getObservable();
employee.age= 28;
    observable.subscribe(s-> System.out.println(s));
}

private static class Employee{
    String name;
    int age;
    Observable getObservable(){
        return Observable.just(name, age);
    }
}复制代码

上面的代码会输出什么呢?若是你的答案是 age = 28 那就大错特错了。基本上全部建立 Observable 对象的方法在建立时就记录了可用的值。就像刚才的数据实际上输出的是 age = 27 , 由于在我建立 Observable 的时候 age 值是 27 ,当我把 age 的值变成 28 的时候 Observable 类已经建立过了。因此怎么解决这个问题呢?是的,这个时候就轮到 defer 这个 API 出场了。太有用了!当你使用 defer 之后,只有注册(subscribe)的时候才建立 Observable 类。用这个 API ,我就能够得到想要的值。

Observable getObservable(){
  //return Observable.just(name, age);
  return Observable.defer(()-> Observable.just(name, age));
}复制代码

这样咱们的 age 的输出值就是 28 了。

(校对 Phoenix 注:Observable 的建立方法中,并非像原文中写到的,“基本上全部建立 Observable 的方法在建立时就记录了可用的值”。而是只有 just, from 方法。 create , fromCallable 等等方法都是在 subscribe 后才会调用。文中的例子可使用 fromCallable 代替 defer。)

9 error()

一个能够弹出错误提示的方法。当咱们讨论 Observer 类和他的方法的时候,我再和你分享吧。

10 never()

这个 API 建立出的 Observable 对象没有包含泛型。

(译者注:Observable.never 虽然能够获得一个 Observable 对象,可是注册的对应 Observer 既不会调用 onNext 方法也不会 onCompleted 方法,甚至不会调用 onError 方法)

我:哇哦。谢谢你,Observable 类。谢谢你耐心又详细的回答,我会把你的回答记在个人秘籍手册上的。话说,你能够把函数也转化成 Observable 对象吗?

Observable 类:固然,注意下面的代码。

public static void main(String[] args) throws InterruptedException {
    System.out.println(scale(10,4));
    Observable.just(scale(10,4))
            .subscribe(value-> System.out.println(value));
}

private static float scale(int width, int height){
    return width/height*.3f;
}复制代码

我:哇哦,你真的好强大。如今我想问你有关操做符,好比 map ,filter 方面的问题。可是有关 Observable 对象建立,若是还有什么我由于缺少知识没问到的地方,再多告诉我一点呗。

Observable 类:其实还有不少。我在这里介绍两类 Observable 对象。一种叫作 Cold Observable,第二个是 Hot Observable。在...

总结:

你们好。这篇对话已经很是很是的长,我须要就此搁笔了。否则这篇文章就会像大部头的书,可能看上去不错,可是主要目的就跑偏了。我但愿,咱们能够按部就班的学习。因此我要暂停个人对话,而后在下一篇继续。读者能够试试亲自实现这些方法,若是可能的话在实际的项目中去运用、重构。最后我想说,谢谢 Observable 类给我了这么多他/她的时间。

周末愉快,再见~


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOSReact前端后端产品设计 等领域,想要查看更多优质译文请持续关注 掘金翻译计划

相关文章
相关标签/搜索