从普通Java事件创建Observable

Ale*_*nov 22 java events event-handling rx-java

Observable从传统的Java事件模式创建Rx-Java的最佳方法是什么?也就是说,给定

class FooEvent { ... }

interface FooListener {
  void fooHappened(FooEvent arg);
}

class Bar {
  public void addFooListener(FooListener l);
  public void removeFooListener(FooListener l);
}
Run Code Online (Sandbox Code Playgroud)

我想实施

Observable<FooEvent> fooEvents(Bar bar);
Run Code Online (Sandbox Code Playgroud)

我想出的实现是:

Observable<FooEvent> fooEvents(Bar bar) {
  return Observable.create(new OnSubscribeFunc<FooEvent>() {
    public Subscription onSubscribe(Observer<? super FooEvent> obs) {
      FooListener l = new FooListener() {
        public void fooHappened(FooEvent arg) {
          obs.onNext(arg);
        }
      };

      bar.addFooListener(l);

      return new Subscription() {
        public void unsubscribe() {
          bar.removeFooListener(l);
        }
      };
    }
  }); 
}
Run Code Online (Sandbox Code Playgroud)

但是,我真的不喜欢它:

  1. 它非常冗长;

  2. 需要一个监听器Observer(理想情况下,如果没有观察者,则应该没有监听器,否则一个监听器).这可以通过将观察者计数保持为一个字段,OnSubscribeFunc在订阅时递增它并在取消订阅时递减来改进.

有更好的解决方案吗?

要求:

  1. 使用事件模式的现有实现而不更改它们(如果我控制该代码,我可以将其写入以返回Observable我需要的).

  2. 如果/源API发生更改时获取编译器错误.不使用Object实际的事件参数类型或属性名称字符串.

epb*_*epb 7

我认为没有办法为每个可能的事件创建一个通用的observable,但你可以在任何需要的地方使用它们.

RxJava源代码有一些方便的示例,说明如何从鼠标事件,按钮事件等创建observable.看一下这个类,它从KeyEvents创建它们:KeyEventSource.java.


Yar*_*hiy 7

您的实施绝对正确.

它非常冗长

使用lambdas(RxJava 2的示例)变得更加冗长:

Observable<FooEvent> fooEvents(Bar bar) {
    return Observable.create(emitter -> {
        FooListener listener = event -> emitter.onNext(event);
        bar.addFooListener(listener);
        emitter.setCancellable(() -> bar.removeFooListener(listener));
    }); 
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,如果没有观察者,则应该没有听众,否则就应该有一个听众

您可以使用share()运算符,这使您的可观察性变得,即所有订阅者共享单个订阅.它会自动订阅第一个订阅者,并在最后一个取消订阅时取消订阅:

fooEvents(bar).share()
Run Code Online (Sandbox Code Playgroud)