RequestFactoryEditorDriver在刷新后获取编辑后的数据
让我从我有一个解决方案开始,但我并不认为它很优雅。所以,我正在寻找更干净的方式来做到这一点。RequestFactoryEditorDriver在刷新后获取编辑后的数据
我有一个EntityProxy显示在视图面板中。视图面板是一个只使用显示模式的RequestFactoryEditorDriver。用户点击一个数据元素并打开一个弹出编辑器来编辑EntityProxy的一个数据元素,其数据位数比查看面板中显示的少一些。当用户保存元素时,我需要查看面板来更新显示。
我遇到了一个问题,因为弹出式编辑器流程的RequestFactoryEditorDriver不允许您访问编辑的数据。驱动程序使用上下文中用于发送服务器数据的上下文,但即使将其转换为edit()调用中存储在编辑器驱动程序中的上下文类型,上下文仅允许使用Receiver<Void>
。 [它似乎没有发送和EntityProxyChanged事件,所以我无法听取它并更新显示视图。 - 从头开始 - 我现在看到这个事件不是针对这个用例的]
我找到的解决方案是改变我的域对象,坚持返回新保存的实体。然后,像这样创建
editor.getSaveButtonClickHandler().addClickHandler(createSaveHandler(driver, editor));
// initialize the Driver and edit the given text.
driver.initialize(rf, editor);
PlayerProfileCtx ctx = rf.playerProfile();
ctx.persist().using(playerProfile).with(driver.getPaths())
.to(new Receiver<PlayerProfileProxy>(){
@Override
public void onSuccess(PlayerProfileProxy profile) {
editor.hide();
playerProfile = profile;
viewDriver.display(playerProfile);
}
});
driver.edit(playerProfile, ctx);
editor.centerAndShow();
弹出的编辑器然后在保存处理我只是火()的情况下,我从冲洗得到()。虽然这种方法有效,但看起来并不正确。 [似乎我应该在显示视图中订阅entitychanged事件,并从那里更新实体和视图。 - 再次从头开始,与之前的原因相同]这种方法也保存完整的实体,而不仅仅是改变的位,这将增加带宽使用。
我认为应该发生的事情是,当你刷新实体时,它应该'乐观地'更新实体的射频管理版本并触发实体代理更改的事件。只有在保存中出现问题时才能恢复实体。实际的保存应该只发送更改的位。以这种方式,不需要重新提取整个实体并通过电线两次发送完整的数据。
有没有更好的解决方案?
我找到了一个更好的解决方案。在调用RequestFactoryEditorDriver edit()并将可编辑代理保存为我的视图代理之前,我使代理可编辑。
PlayerProfileCtx ctx = rf.playerProfile();
playerProfile = ctx.edit(playerProfile);
driver.edit(playerProfile, ctx);
另外,(我想我以前曾试图这样做,它没有工作,但我一定是做错了什么事,然后)我可以投的是来自于回冲的上下文。这与我拨打edit()
调用的驱动程序相同,因此它很安全。
PlayerProfileCtx ctx = (PlayerProfileCtx) driver.flush();
这样做解决了rf用fire()发送整个对象而不仅仅是diff的问题。我不知道为什么。这可能是RF Editor Driver中的一个错误。
所以现在我已经从视图中获得了驱动程序的数据,并且不必依赖从服务器发回它。但是我注册了EntityProxyChange事件,所以如果服务器发生冲突,我可以检测并重新获取。
你似乎并没有真正理解RF的细节;另外,你的术语并没有真正帮助理解(冲水与火灾)。
RF中的代理服务器是您检索服务器时的状态快照。您可以通过其他代理服务器中的其他位置对实体进行任何操作,但您的代理服务器永远不会改变以反映这些修改。
EntityProxyChange
事件在服务器检测到它已更改时在客户端(对于服务器已知且已从客户端发送的实体)调度:其版本(由getVersion
在Locator
)已经改变,或者它已被删除(如Locator
的isLive
方法所述)。如果您不使用Locator
,它将使用实体的getVersion
,并且isLive
将被find
替换为实体的ID(由其getId
方法返回)并检查null
(这也是默认实现的isLive
在Locator
)。
就你而言,如果你没有看到EntityProxyChange
被调度,那么检查你是否正确地更新了实体的版本。
最后,RF总是将您的更改差异发送到服务器(ValueProxy
除外,在这种情况下差异无意义)。至于检索数据,默认情况下它不会检索链接的代理,除非您明确要求使用with
;这与您可能发送的实体无关。
你的情况,更新视图面板,你有3种可能性:
- 从服务器获取代理回(听
EntityProxyChange
事件或从弹出一个明确的信号之后,你可以使用find
方法RequestContext
与代理的stableId
作为参数,适当的with
为您需要的属性)。
由于您正在执行第二个HTTP请求,它有点低效,但另一方面它可以处理来自应用程序中其他地方的更改(它们也会触发EntityProxyChange
事件) - 在相同的HTTP中检索更新后的代理请求作为您用来保存的请求:请求您的请求上下文的
save
方法返回已保存的实体,或者在相同的HTTP请求中将同一请求上下文中的find
方法调用批次,save
和find
。
这就是你所做的。它发送更改的差异并检索您的视图面板所需的属性。人们可以说它有弹性和视图面板紧密耦合的缺点,这取决于你是否可以接受的权衡。 - 使用您编辑的实体并将其发送到您的视图面板中的服务器,并且没有额外的数据。
虽然这看起来更简单,但您会错过其他用户可能对该实体进行的任何更改(仅更改已知的服务器)。
总而言之,我想我会采用目前的解决方案。关于你的代码,我想启动带代理和回调的弹出窗口,并将请求上下文和编辑编辑器驱动程序作为弹出窗口的实现细节:只需要它在完成时调用视图面板,将更新后的代理作为参数传递给回调函数。
有关术语的最后一句话:你刷新编辑司机到字段的值复制回对象/代理,和(独立,但如果连续的),你火发送批请求上下文的服务方法和对服务器的代理更改。刷新编辑器驱动程序不会向服务器发送任何内容,这些都是不同的操作。
感谢您的回答,但我不确定您认为我在哪里混合冲水和火灾。我完全按照你所描述的使用它们。同样在RequestFactoryEditorDriver中,flush会返回你初始化它的rf上下文,而不是被编辑的对象,这会阻止你的第三个选项成为可能(除非有一些存取程序找不到)。同时查看发送的http请求,整个实体将被发送到服务器,而不仅仅是增量 - 这与rf的记录方式不同。并且,当您为EntityProxyChange事件提供的条件是什么条件时... – Deanna 2012-03-20 18:09:37
我已经考虑过您的选项1,但正如您所指出的那样,它是对服务器的额外往返。我曾使用过选项2,但由于它不发送差异,因此无法按预期工作。在这个过程开始之前,实体已经存在于服务器上,并进入视图面板。这是我在示例代码中引用的playerProfile。我使用它来初始化RequestFactoryEditorDriver,所以当驱动程序刷新和/或要更新的原始代理时,我希望事件触发(事件总线触发不是rf)。我错过了阻止这些事情的东西吗? – Deanna 2012-03-20 18:16:19
另外,我没有完全理解entityproxy的用例,它只是抓取它时的快照。那你是对的。我认为这是一个更实用的功能,如实体的远程/客户端副本,如果我从服务器中获取同一实体的新副本并发送entityproxychange事件,则会更新该实体。 – Deanna 2012-03-20 18:22:59