按钮不应该知道表,并且只能保留为单击流。 因此,该解决方案被丢弃:
final ETable table = ...
PublishSubject<ItemSelected> selected = PublishSubject.create();
button.addSelectionListener(new SelectionListener(){
@Override
public void widgetSelected(SelectionEvent e) {
for (TableItem item : table.getSelection()) {
selected.onNext(new ItemSelected(item));
}
}
});
我更喜欢使用表的项目选择流组成按钮的单击流,以保持这两个元素之间的松散耦合。由于表允许多个选择,我必须首先
Scan
为了发出所有项目的事件,选择的项目。类似:
public static class ItemsSelected<T> {
final List<T> items = new ArrayList<T>();
}
public abstract static class ItemSelection<T> {
public abstract void apply(ItemsSelected<T> selection);
}
public static class ItemUnselected<T> extends ItemSelection<T> {
final T item;
public ItemUnselected(T item) {
this.item = item;
}
public void apply(ItemsSelected<T> selection) {
selection.items.remove(item);
}
}
public static class ItemSelected<T> extends ItemSelection<T> {
final T item;
public ItemSelected(T item) {
this.item = item;
}
public void apply(ItemsSelected<T> selection) {
selection.items.add(item);
}
}
public static class ObservableTable<T> extends Table {
private PublishSubject<ItemSelection<T>> clicks = PublishSubject.create();
public Observable<ItemsSelected<T>> selection = clicks.scan(new ItemsSelected<T>(),
new Func2<ItemsSelected<T>, ItemSelection<T>, ItemsSelected<T>>() {
@Override
public ItemsSelected<T> call(ItemsSelected<T> t1, ItemSelection<T> t2) {
// breaking events immutability
t2.apply(t1);
return t1;
}
});
public ObservableTable(Composite parent, int style) {
super(parent, style);
this.addSelectionListener(new SelectionListener() {
@SuppressWarnings("unchecked")
@Override
public void widgetSelected(SelectionEvent e) {
if (((TableItem) e.item).getChecked())
clicks.onNext(new ItemSelected<T>((T) e.item.getData()));
else
clicks.onNext(new ItemUnselected<T>((T) e.item.getData()));
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
}
}
-------S1--U1-----S2---S3--------- table.clicks
(scan)
-------(1)--()---(2)---(2,3)------ table.selection
----O----------O-------------O---- button.clicks
(?)
-----------------------------(2,3) selectionForAction
,我应该使用哪个操作?
zip:它不起作用,因为如果我单击按钮并以后选择一个项目,它不应该做任何事情,但是使用zip会发出事件。join:我最终使用
jointable.selection.join(button.clicks, new Func1<ItemsSelected,Observable<Long>>() {
@Override
public Observable<Long> call(ItemsSelected t) {
// it doesn't seem a good idea
return Observable.timer(1, TimeUnit.DAYS);
}
}, new Func1<ClickEvent, Observable<Long>>() {
@Override
public Observable<Long> call(ClickEvent t) {
// this makes the ClickEvent be dropped if there is no previous ItemsSelected event emitted
return Observable.timer(1, TimeUnit.MILLISECONDS);
}
}, new Func2<ItemsSelected, ClickEvent, SelectionForAction>() {
@Override
public SelectionForActioncall(ItemsSelected t1, ClickEvent t2) {
return new SelectionForAction(t1.items);
}
});
任何想法?join行为所需的操作员。
以
sample的一个varianiant在我的示例中,点击充当采样器,流选择会发出我感兴趣的事件。 其他可能的解决方案将使用
截止器(边界):
点击流将充当边界,我可以避免使用Scan
因此,在示例中,我实现了最初的目标,但是,我对处理项目的方式和所选项目的最终列表不满意。 在这种情况下,我需要维护所选项目的状态,以便在发生Clickevent时对所有操作执行所有操作。
我可以订阅项目选择/取消选择并维护所选项目的列表,但随后我会失去可观察到的可观察到的点击的可能性。与sscani保持状态并保持可观察力的合成性,但是将当前选择列表表示为事件似乎有些强制,实际上这代表了一个新问题:如果我选择x项目,然后单击按钮,然后单击按钮,随着预期的选择,带有选择的事件正在排放,但是如果未选择项目或选择新项目,然后再次单击按钮,则不会发生任何事情。因此,似乎选择并不适合事件。