RxJava 而不是接口回调(Android)

RxJava instead of interface callbacks ( Android)

RxJava 的新手,我对接口回调(通过接口变量从代码的内部 layer/module 调用)与 RxJava 有疑问。 为了更清楚,快速示例:

标准回调接口实现,接口,classA和B

interface CustomCallback {
    void onCallbackCalled(String str);
}
class ClassA {
    private ClassB classB;
    public ClassA() {
        classB = new ClassB(new CustomCallback() {
            @Override
            public void onCallbackCalled(String str) {
                System.out.println("Callback called " + str);
            }
        });
    }
}
class ClassB {
    private CustomCallback customCallback;
    public ClassB(CustomCallback callback) {
        customCallback = callback;
    }
    private void somethingHappened() {
        customCallback.onCallbackCalled("method somethingHappened");
    }
}

当调用classB方法"somethingHappened"时,结果为:"Callback called method somethingHappened"。 接口的方法 onCallbackCalled(String str) 可以从 classB 调用任意多次 .

CLASS一个↓................................................ ......通过构造函数注入接口

CLASS B................↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ onCallbackCalled(...) 0... n个

现在是 RxJava。我发现的 99% 的案例。

class ClassA {
    private ClassB classB;
    public ClassA() {
        classB = new ClassB();
    }

    public void rxJavaMethod() {
                DisposableObserver<String> observer = classB.getObservable()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(new DisposableObserver<String>() {

                    @Override
                    public void onNext(String s) {}

                    @Override
                    public void onError(Throwable e) {}

                    @Override
                    public void onComplete() {}
                });
    }
}

class ClassB {
    private Observable<String> getObservable() {
        return Observable.just(can be different from "just", for sake of example);
    }
}

方案是:

CLASS A ↓................................ 一次获取Observable资源的调用

CLASS B................↑ EDIT returns observable 发射 0.. .n 值

所以基本上你从顶层调用(在这个例子中),你从内层得到关于状态的响应。

问题:

1) 如果你有一个动态变化的模型(内层)(但不是任何类型的 AsyncTask 等),并且你想通知顶层(例如 UI)该状态已更改(很好的例子:游戏)。

2) RxJava 库中是否有任何类型的 "bridge" class (我认为它是“订阅它,然后你可以向它传递任意多次参数,并且information/observable 将发送给订阅者。

3) 尝试这样做而不是标准接口回调是否有任何意义和优势(在上述情况下,不是“单击按钮,获得一次响应”)

更新,基于上述示例的答案

正如 Bob Dalgleish 提到的,建立这种桥梁的方法是使用 class 扩展 Subject rxjava 之一。 http://reactivex.io/documentation/subject.html

class ClassA {
    private ClassB classB;
    public ClassA() {
        classB = new ClassB();
    }

    public void rxJavaMethod() {
                DisposableObserver<String> observer = classB.getCallbackSubjectRx()
                .subscribeWith(new DisposableObserver<String>() {

                    @Override
                    public void onNext(String s) {}

                    @Override
                    public void onError(Throwable e) {}

                    @Override
                    public void onComplete() {}
                });
    }
}

class ClassB {
    private BehaviorSubject<String> mCallbackRx;
    public ClassB() {
        mCallbackRx = BehaviorSubject.create();
    }

    // method somethingHappened can be invoked whenever whe want and
    // it will send given parameter to all subscribers
    private void somethingHappened() {
        mCallbackRx.onNext("method somethingHappened");
    }

    // multiple subscribers allowed
    public BehaviorSubject<String> getCallbackSubjectRx() {
        return mCallbackRx;
    }
}

缺点可能是,如果我们想使用一个 "bridge" 来处理多个回调类型(接口有方法,我们只使用一个方法:"onNext()"),我们可能需要创建包装器class 带回调参数。在我看来这不是什么大问题。

另一方面,我们可以访问所有 RxJava 运算符。 http://reactivex.io/documentation/operators.html

(上面的示例是针对 RxJava2 的,其中 Disposable 基本上是从 RxJava1 订阅)。

首先要注意的是

CLASS B................↑ returns 0...n observables to observer

不正确。 Class B returns 一个 observable,它偶尔会发出 0..n 个值。

  1. (问题不清楚)。来自 class B 的内部 observable,无论出于何种原因正在改变状态。最常见的原因是另一个 process/task/thread 正在喂它,而您想在 UI.

  2. 中显示结果状态
  3. 一种简单的 "bridging" class 类型,我一直在使用几个 Subject<> class 中的任何一个。您可以使用 .onNext() 向他们发送新值,订阅者将获得这些值。

  4. 如果回调接口都标准化了,那倒是有一些优势,但是各地都不一样。您必须记住,对于您正在查看的这个东西,您需要一些特定的界面,而对于另一个东西,则需要一个不同的界面。虽然现在 UI 事件趋于统一,但尝试将 UI 事件与网络事件和数据库事件混合使用仍然会让您感到不知所措。具有更小的 class 接口,大部分封装在 rxJava 泛型 classes 中,使得组合功能更容易。

编辑:改进示例代码。

Yammer Engineering 有一篇关于使用 Observable.create() 的好文章(以前是 Observable.fromEmitter(),以前是 Observable.fromAsync()。他提出的要点是

  1. 使用 Observable.create() 通过向底层接口注册侦听器来为您处理订阅步骤。更重要的是,它安排在 unsubscribe() 发生时注销侦听器。

  2. 开箱即用,此代码处理多个订阅者,每个订阅者接收其自己的可观察数据流。

  3. 正如我上面提到的,侦听器协议特定于您注册的对象。如果该事物仅支持单个侦听器,那么您可能希望引入一个订阅被观察事物的 Subject,而所有其他观察者都订阅该主题。

编辑结束。

我最喜欢的解组合示例是 distinctUntilChanged() 运算符。因为它是一个适用于通用可观察对象的运算符,所以它封装了有状态 属性 保存连续值以进行比较并且只发出不同的值。我经常用它来记录状态变化。要使用标准回调接口达到相同的目的,需要添加一个不同的接口来将先前的值保存到每个现有接口。

所以,是的,大多数时候值得使用 rxJava observables 方法,只是为了不必记住当前情况下可能适用的许多回调协议中的哪一个。