在java方法everything is passed-by-value so i can change the object attributes passed to the method and expect that the original object attributes are changed中。但在这种方法中,我得到了不同的结果:
我有这个方法:
public Observable<Menu> makeMenu(Menu menu, NumberSettingChanges.MenuChanges changes) {
// Start flow with added and edited extensions
return Observable.from(changes.added.entrySet())
.mergeWith(Observable.from(changes.edited.entrySet()))
//Upload announcement voices or do nothing if extension is not an announcement
.flatMap(e -> {
if (AppTypeContract.APP_TYPE_ANNOUNCEMENT.equals(e.getValue().type)) {
return mMediaManager.uploadAsync(e.getValue().config.localPrompt)
.doOnNext(response -> {
//Update extension prompt with the storage path.
menu.config.extensions.get(e.getKey()).config.prompt = response.mPath;
menu.config.extensions.get(e.getKey()).config.localPrompt = "";
})
.flatMap(response -> Observable.just(e));
} else {
return Observable.just(e);
}
}
)
}
我在flatmap中操作菜单属性:
menu.config.extensions.get(e.getKey()).config.localPrompt = "";
我在同一个类中调用该方法:
public Observable<NumberSetting> saveSettings(NumberSetting o, NumberSetting n) {
NumberSettingChanges changes = compareNumberSetting(o, n);
return makeMenu(n.day, changes.day)
.mergeWith(makeMenu(n.night, changes.night));
}
最后:
saveSettings(ns, mNumberSettingNew).subscribe();
我的期望是mNumberSettingNew.menu.config.extensions.get(e.getKey()).config.prompt
已更改,但此次调用后没有发生任何变化且mNumberSettingNew
根本没有变化。
请注意,我确信更改提示行是在调试中完成的。
答案 0 :(得分:1)
我认为我不能解释Java的参数语义比你在第一段中引用的链接更好(甚至一半),所以我不会尝试。重点是:Java中的所有内容都是通过值传递的(即复制的),但是对象的复制内容不是对象本身,而是对象的引用。换句话说,引用按值传递。
关于您的特定问题:是的,如果您将对可变对象的引用传递给某些rx-java代码,则该引用将指向该对象的同一实例。如果您改变实例,那么调用者代码也将能够看到更改,因为它们是在同一实例上进行的。那是因为rx-java仍然只是Java,不能改变该级别的语言语义。
如果没有看到整个代码,我不确定这里会出现什么问题......您何时检查mNumberSettingsNew
是否确实在doOnNext
中进行了更改?如果您在saveSettings(ns, mNumberSettingNew).subscribe();
uploadAsync
之后立即检查,Subscriber
可能尚未返回。您可以尝试在subscribe
中添加实际scan
并检查结果。
更一般地说,我认为你应该在使用rx-java时尽量避免像这样的副作用。您的情况 - 获取输入对象,对该对象应用一组(可能是异步的)更改,并等待更改的输出对象 - 有点棘手,但我认为可以使用Observable.from(changes.added.entrySet())
.mergeWith(Observable.from(changes.edited.entrySet()))
.scan(menuBeforeAnyChanges, new Func2<Menu, Change, Menu>() {
public Menu call(final Menu previousVersionOfTheMenu, final Change nextChange) {
// since I don't know of a version of scan that can return
// an Observable you would I think you would have to adapt
// your code in here to be fully synchronous - but of
// course the scan itself could run asynchronously
final newVersionOfTheMenu = previousVersionOfTheMenu.applyChange(nextChange);
return newVersionOfTheMenu;
}
)
完成。也许是含糊不清的东西:
added
这将采用菜单的原始版本,连续应用edited
和Subscriber<Menu>
和/ emit /每个更新版本菜单的所有更改。因此,您不会产生任何副作用,只需使用last()
订阅该观察结果,然后选择reduce
菜单即可应用所有更改的菜单。
编辑:哦,我刚刚看到另一个名为scan
的方法可以做到这一点:首先last
然后takeLast
或{{1 }}