从普通Java事件创建可观察对象

从普通Java事件创建可观察对象,java,events,event-handling,rx-java,Java,Events,Event Handling,Rx Java,从经典Java事件模式创建Rx Java可观察的的最佳方法是什么?也就是说 class FooEvent { ... } interface FooListener { void fooHappened(FooEvent arg); } class Bar { public void addFooListener(FooListener l); public void removeFooListener(FooListener l); } 我想实施 Observable<

从经典Java事件模式创建Rx Java
可观察的
的最佳方法是什么?也就是说

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);
        }
      };
    }
  }); 
}
可观察事件(条形){
return Observable.create(新建onsubscribeefunc()){

publicsubscriptiononsubscribe(Observer如果你想要一些简单的内置功能,试试这种方法

网站上有一个片段展示了如何使用它

package com.javacodegeeks.snippets.core;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class BeanPropertyChangeEventListener {

    public static void main(String[] args) throws Exception {

        Bean bean = new Bean();
        bean.addPropertyChangeListener(new MyPropertyChangeListener());

        bean.setProperty1("newProperty1");
        bean.setProperty2(123);


        bean.setProperty1("newnewProperty1");
        bean.setProperty2(234);

    }

    public static class MyPropertyChangeListener implements PropertyChangeListener {
        // This method is called every time the property value is changed
        public void propertyChange(PropertyChangeEvent evt) {
            System.out.println("Name = " + evt.getPropertyName());

  System.out.println("Old Value = " + evt.getOldValue());

  System.out.println("New Value = " + evt.getNewValue());

  System.out.println("**********************************");
        }
    }

    public static class Bean {

        private PropertyChangeSupport pcs = new PropertyChangeSupport(this);

        // Property property1
        private String property1;
        // Property property2
        private int property2;

        public String getProperty1() {
            return property1;
        }
        public void setProperty1(String property1) {
            pcs.firePropertyChange("property1", this.property1, property1);
            this.property1 = property1;
        }

        public int getProperty2() {
            return property2;
        }
        public void setProperty2(int property2) {
            pcs.firePropertyChange("property2", this.property2, property2);
            this.property2 = property2;
        }

        public void addPropertyChangeListener(PropertyChangeListener listener) {
            pcs.addPropertyChangeListener(listener);
        }

    }

}

这很简单

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


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

我想如果您使用另一层监听器作为实际回调和观察者之间的桥梁,您也可以得到同样的结果。
实际回调→ 桥回调→ 观察员

好处:

  • 更多线性码
  • 实际回调的一个实例,在observer之外
  • 对于高阶函数,如函数 kotlin中的文字:
Ex(注意创建可观察闭包有多小):

class LocationService@Inject构造函数(私有val-GoogleapClient:GoogleapClient):ConnectionCallbacks{
val locationObservable:可观察的
私有变量passToObservable:(位置?->Unit={}
初始化{
locationObservable=Observable.create{subscription->
passToObservable={location->
subscription.onNext(位置)
}
}doOnSubscribe先生{
GoogleAppClient.registerConnectionCallbacks(此)
GoogleAppClient.connect()
}杜努恩先生{
GoogleAppClient.unregisterConnectionCallbacks(此)
}
}
覆盖未连接的乐趣(连接提示:捆绑?){
val location=LocationServices.FusedLocationApi.getLastLocation(GoogleAppClient)
passToObservable(位置)
}
覆盖连接已挂起(原因:Int){
//...
}
}

您的实现是绝对正确的

太冗长了

使用lambdas(例如RxJava 2)时,它的详细程度要小得多:


我建议看一看(如果您可以将番石榴添加到项目中),为什么不使用默认实现?@RC.guava事件总线在许多方面都很好,但它没有RxJava的调度程序或事件流组合器。@astinx请参阅我对Leonardo Kenji答案的评论。1.我想要一些可以处理任何事件的东西(例如,鼠标单击、重新绘制等)。并非所有事件都是属性更改!2.这种方法必须处理字符串属性名称。如果属性名称更改或删除,则不会出现编译器错误。3.类型不安全(您的侦听器中只会有一个
对象
。@AlexeyRomanov这是公平的,但我猜不到,可以吗?:-)我建议您在问题中添加这些限制,这样我们可以更好地帮助您。
package com.javacodegeeks.snippets.core;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class BeanPropertyChangeEventListener {

    public static void main(String[] args) throws Exception {

        Bean bean = new Bean();
        bean.addPropertyChangeListener(new MyPropertyChangeListener());

        bean.setProperty1("newProperty1");
        bean.setProperty2(123);


        bean.setProperty1("newnewProperty1");
        bean.setProperty2(234);

    }

    public static class MyPropertyChangeListener implements PropertyChangeListener {
        // This method is called every time the property value is changed
        public void propertyChange(PropertyChangeEvent evt) {
            System.out.println("Name = " + evt.getPropertyName());

  System.out.println("Old Value = " + evt.getOldValue());

  System.out.println("New Value = " + evt.getNewValue());

  System.out.println("**********************************");
        }
    }

    public static class Bean {

        private PropertyChangeSupport pcs = new PropertyChangeSupport(this);

        // Property property1
        private String property1;
        // Property property2
        private int property2;

        public String getProperty1() {
            return property1;
        }
        public void setProperty1(String property1) {
            pcs.firePropertyChange("property1", this.property1, property1);
            this.property1 = property1;
        }

        public int getProperty2() {
            return property2;
        }
        public void setProperty2(int property2) {
            pcs.firePropertyChange("property2", this.property2, property2);
            this.property2 = property2;
        }

        public void addPropertyChangeListener(PropertyChangeListener listener) {
            pcs.addPropertyChangeListener(listener);
        }

    }

}
class LocationService @Inject constructor(private val googleApiClient: GoogleApiClient) : ConnectionCallbacks{

    val locationObservable: Observable<Location>    

    private var passToObservable: (Location?) -> Unit = {}

    init {
        locationObservable = Observable.create<Location> { subscription ->
            passToObservable = { location ->
                subscription.onNext(location)
            }
        }.doOnSubscribe {
            googleApiClient.registerConnectionCallbacks(this)
            googleApiClient.connect()
        }.doOnUnsubscribe {
            googleApiClient.unregisterConnectionCallbacks(this)
        }
    }

    override fun onConnected(connectionHint: Bundle?) {
        val location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient)
        passToObservable(location)
    }

    override fun onConnectionSuspended(cause: Int) {
        //...
    }
}
Observable<FooEvent> fooEvents(Bar bar) {
    return Observable.create(emitter -> {
        FooListener listener = event -> emitter.onNext(event);
        bar.addFooListener(listener);
        emitter.setCancellable(() -> bar.removeFooListener(listener));
    }); 
}
fooEvents(bar).share()