在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);
}
}
)
}我在平面图中操作菜单属性:
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也没有任何变化。
请注意,我确信在调试中已经完成了更改提示符行。
发布于 2015-08-18 08:17:38
我不认为我能更好地解释Java的参数语义(甚至是第一段中引用的链接的一半),所以我不会尝试。要点是: Java中的所有内容都是通过值(即复制)传递的,但是对于对象,复制的不是对象本身,而是对对象的引用。换句话说,引用是通过值传递的。
因此,关于您的特定问题:是的,如果将对可变对象的引用传递给某些rx代码,则引用将指向该对象的同一个实例。如果您改变了实例,那么调用方代码也将能够看到更改,因为它们是在同一个实例上进行的。这是因为rx仍然只是Java,不能在该级别上更改语言语义。
没有看到整个代码,我不知道这里会有什么问题.您何时检查mNumberSettingsNew是否实际对doOnNext进行了更改?如果在saveSettings(ns, mNumberSettingNew).subscribe();之后立即检查,您的uploadAsync可能还没有返回。您可以尝试在您的Subscriber中添加一个实际的subscribe并检查那里的结果。
总的来说,我认为在使用rx时,您应该尽量避免这样的副作用。您的情况--以一个输入对象为例,对该对象应用一组(可能是异步的)更改,并等待更改的输出对象--有点棘手,但我认为可以用scan来完成。也许是这样模糊的东西:
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的所有更改,并/emit/每个更新的菜单版本。因此,您不会有任何副作用,只需使用Subscriber<Menu>订阅可观察到的内容,然后接受last()菜单,这将是应用所有更改的菜单。
编辑:哦,我刚刚看到了另一个叫做reduce的方法,它就是这样做的:首先是scan,然后是last或takeLast。
https://stackoverflow.com/questions/32063496
复制相似问题