9

给定 Java 对象上的任意字段,我想创建一个 Observable 来监视该字段,并在每次字段值更改时将新结果推送到 Observer。ReactiveCocoa 有一个名为 RACObserve 的宏,它似乎正是这样做的。

我想知道如何使用 RxJava 实现类似的功能。

例如,假设我有以下简单的类:

public class Foo {
    enum State {
        Idle,
        Ready,
        Error
    }

    private State currentState = State.Idle;

    //methods that can change currentState
}

我想创建一个Observable<State>每次更改currentState.

在 ReactiveCocoa 中,看起来我会写一些类似下面的东西(请原谅我的伪 Objective-C):

[RACObserve(self, currentState) subscribeNext:^(NSString *newState) {
    NSLog(@"%@", newState);
}];

我如何在 RxJava 中实现类似的功能?我在想我可能需要将所有对 currentState 的更改包装在一个 setter 中,但我不清楚我应该在哪里调用 Observable.create 以及如何将 currentState 的更改提供给 Observer。

4

4 回答 4

3

ReactiveCocoa 实际上更类似于 ReactiveUI ( http://www.reactiveui.net ) 而不仅仅是普通的 Rx。在 ReactiveUI 中,你可以使用 this.WhenAnyValue(x => x.PropName) 来做你想做的事。

于 2014-03-03T05:22:59.837 回答
1

我最近偶然发现了同样的问题,我最终使用了 PropertyChangeListener,它会在属性更改时发出一个对象,请参见以下内容:

更新监听器:

public class GameUpdateListener {

public static Observable<Object> changed(Game game) {
    final BehaviorSubject<Object> subject = BehaviorSubject.create((Object)game);

    game.addPropertyChangeListener(new PropertyChangeListener() {
        @Override
        public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
          subject.onNext( (Object)propertyChangeEvent.getNewValue());
        }
    });
    return subject;
  }
}

一些自定义对象:

public class Game {
 private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
...
  public setSomeField(String field){
       this.field = field;
       pcs.firePropertyChange("field", this.field, field);

}

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

...

}

观察:

Game game = new Game();
GameUpdateListener listener = new GameUpdateListener();

final Observable<Object> gameObserver = listener.changed(game);

    gameObserver.subscribe(new Action1<Object>() {
        @Override
        public void call(Object o) {
            Log.e(TAG, "Object Changed");
        }
    });


game.setSomeField("New value");

只要您不需要再次实例化您的对象,这将正常工作。也许对此的解决方案是创建一个本地 setter 方法并在那里发出更改。

于 2014-04-09T05:45:06.353 回答
0

我认为你所追求的是一个Subject<T>. 它实现了IObserver<T>,因此您可以调用OnNext(T)以触发新值,以及IObservable<T>,您可以将其公开公开以便可以订阅。

如果您需要它向新订阅者触发最新值,您可以使用ReplaySubject<T>缓冲区大小为 1 的 a。

这是一个基本的实现:

public class SomeService
{
    private Subject<int> values = new Subject<int>();

    public IObservable<T> Values
    {
        get
        {
            // AsObservable prevents it from being cast back to Subject
            return values.AsObservable();
        }
    }

    // Private; called by some internal mechanism
    private void SetValue(int newValue)
    {
        newValue.OnNext(newValue);
    }
}
于 2014-03-03T05:35:00.423 回答
0

由于您的问题标题包含“或 Rx.NET”,这是我的建议(我不知道 RxJava,您可能会发现类似的东西)。

您可能必须利用 setter 中的某种机制。.NET 中的标准方式是使用INotifyPropertyChanged接口。然后通过触发事件,您可以IObservable<T>使用此流 创建一个Observable.FromEvent<TEvent, TArgs>()

你可以在这里找到一个非常好的例子来说明你想做的事情(.NET)。

Rob Foncesa-Ensor 的学分)

于 2014-01-29T16:18:52.300 回答