了解RxJava:Runnable回调之间的差异

Héc*_*tor 1 callback rx-java

我正在尝试理解RxJava,我确信这个问题是无意义的...我使用RxJava这个代码:

public Observable<T> getData(int id) {

    if (dataAlreadyLoaded()) {
        return Observable.create(new Observable.OnSubscribe<T>(){
            T data = getDataFromMemory(id);
            subscriber.onNext(data);
        });
    }

    return Observable.create(new Observable.OnSubscribe<T>(){
        @Override
        public void call(Subscriber<? super String> subscriber) {
            T data = getDataFromRemoteService(id);
            subscriber.onNext(data);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

并且,例如,我可以这样使用它:

Action1<String> action = new Action<String>() {
    @Override
    public void call(String s) {
        //Do something with s
    }
};

getData(3).subscribe(action);
Run Code Online (Sandbox Code Playgroud)

而另一个回调实现Runnable:

public void getData(int id, MyClassRunnable callback) {

    if (dataAlreadyLoaded()) {
        T data = getDataFromMemory(id);
        callback.setData(data);
        callback.run();
    } else {
        T data = getDataFromRemoteService(id);
        callback.setData(data);
        callback.run();
    }
}
Run Code Online (Sandbox Code Playgroud)

我会这样用它:

getData(3, new MyClassRunnable()); //Do something in run method
Run Code Online (Sandbox Code Playgroud)

哪些是差异?为什么第一个更好?

问题不在于框架本身,而在于范式.我试图了解被动的用例.

我感谢任何帮助.谢谢.

Dan*_*Lew 5

首先,您的RxJava版本要比它需要的复杂得多.这是一个更简单的版本:

public Observable<T> getData(int id) {
  return Observable.fromCallable(() ->
      dataAlreadyLoaded() ? getDataFromMemory(id) : getDataFromRemoteService(id)
  );
}
Run Code Online (Sandbox Code Playgroud)

无论如何,您提出的问题是如此微不足道,以至于两种解决方案之间没有明显区别.这就像询问哪一个更适合分配整数值 - var = var + 1或者var++.在这种特殊情况下它们是相同的,但是当使用赋值时,还有更多的可能性(添加除1以外的值,减去,乘以,除以,考虑其他变量等).

那么你可以用反应来做什么呢?我喜欢reactivex网站上的摘要:

  1. 轻松创建事件流或数据流.对于单个数据而言,这并不是那么重要,但是当您拥有数据流时,范例会更有意义.

  2. 使用类似查询的运算符编写和转换流.在上面的示例中,没有运算符和单个流.运算符允许您以方便的方式转换数据,并且组合多个回调比组合多个回调要困难得多Observables.

  3. 订阅任何可观察的流以执行副作用.你只是在听一个单一的事件.Reactive非常适合收听多个事件.它也适用于错误处理等事项 - 您可以创建一系列长事件,但任何错误都会转发给最终订阅者.


让我们看一个更具体的例子,它有一个更具吸引力的例子:验证电子邮件和密码.你有两个文本字段和一个按钮.您希望在输入电子邮件(假设.*@.*)和密码(至少8个字符)后启用该按钮.

我有两个Observables代表用户当前在文本字段中输入的内容:

Observable<String> email = /* you figure this out */;
Observable<String> password = /* and this, too */;
Run Code Online (Sandbox Code Playgroud)

为了验证每个输入,我可以将输入映射Stringtruefalse.

Observable<Boolean> validEmail = email.map(str -> str.matches(".*@.*"));
Observable<Boolean> validPw = password.map(str -> str.length() >= 8);
Run Code Online (Sandbox Code Playgroud)

然后我可以它们组合起来以确定是否应该启用该按钮:

Observable.combineLatest(validEmail, validPw, (b1, b2) -> b1 && b2)
  .subscribe(enableButton -> /* enable button based on bool */);
Run Code Online (Sandbox Code Playgroud)

现在,每次用户在任一文本字段中键入新内容时,按钮的状态都会更新.我已经设置了逻辑,以便按钮只响应文本字段的状态.

这个简单的例子并未显示所有内容,但它显示了在您通过简单订阅后事情变得更加有趣.显然,你可以在没有反应范式的情况下做到这一点,但是对于被动运算符来说它更简单.