给定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
的值时,都会将新状态推送到Observer。
在ReactiveCocoa中,看起来我会写下类似的东西(请原谅我的伪Objective-C):
[RACObserve(self, currentState) subscribeNext:^(NSString *newState) {
NSLog(@"%@", newState);
}];
我如何在RxJava中实现类似的功能?我想我可能需要在setter中包含对currentState的所有更改,但是我不清楚我应该在哪里调用Observable.create以及如何将currentState的更改提供给Observer。
答案 0 :(得分:3)
ReactiveCocoa实际上与ReactiveUI(http://www.reactiveui.net)更相似,而不仅仅是普通的Rx。在ReactiveUI中,您可以使用this.WhenAnyValue(x =&gt; x.PropName)来完全按照您的意愿执行。
答案 1 :(得分:0)
由于您的问题标题包含“或Rx.NET”,这里是我的建议(我不知道RxJava,您可能会发现类似的东西)。
您可能必须在setter中利用某种机制。 .NET中的标准方法是使用INotifyPropertyChanged
接口。
然后通过触发事件,您可以使用来自此流创建IObservable<T>
Observable.FromEvent<TEvent, TArgs>()
您可以找到一个非常好的例子(.NET)here。
(归功于Rob Foncesa-Ensor)
答案 2 :(得分:0)
我认为你所追求的是Subject<T>
。它实现了IObserver<T>
,因此您可以调用OnNext(T)
来触发新值,以及IObservable<T>
,您可以将其公开公开,以便可以订阅。
如果您需要它来向新订阅者发送最新值,您可以使用缓冲区大小为1的ReplaySubject<T>
。
这是一个基本的实现:
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);
}
}
答案 3 :(得分:0)
我最近遇到了同样的问题,最后我使用了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方法并在那里发出更改。