从普通 Java 事件创建可观察

2022-09-01 21:17:30

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

class FooEvent { ... }

interface FooListener {
  void fooHappened(FooEvent arg);
}

class Bar {
  public void addFooListener(FooListener l);
  public void removeFooListener(FooListener l);
}

我想实现

Observable<FooEvent> fooEvents(Bar bar);

我想出的实现是:

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);
        }
      };
    }
  }); 
}

但是,我真的不喜欢它:

  1. 它相当冗长;

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

有没有更好的解决方案?

要求:

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

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


答案 1

我不认为有一种方法可以为每个可能的事件创建一个通用的可观察量,但你当然可以在任何你需要的地方使用它们。

RxJava 源代码提供了一些方便的示例,说明如何从鼠标事件、按钮事件等创建可观察量。看看这个类,它从KeyEvents创建它们:KeyEventSource.java


答案 2

您的实现是绝对正确的。

它非常冗长

使用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));
    }); 
}

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

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

fooEvents(bar).share()

推荐