RequestFactoryEditorDriver在刷新后获取编辑数据

时间:2012-03-20 15:35:26

标签: gwt requestfactory

首先让我有一个解决方案,但我并不认为它很优雅。所以,我正在寻找一种更清洁的方法来做到这一点。

我在视图面板中显示了EntityProxy。视图面板是仅使用显示模式的RequestFactoryEditorDriver。用户单击数据元素并打开弹出编辑器,以使用比视图面板中显示的数据位数更多的数据来编辑EntityProxy的数据元素。当用户保存元素时,我需要视图面板来更新显示。

我遇到了一个问题,因为弹出编辑器流程的RequestFactoryEditorDriver不允许您访问已编辑的数据。驱动程序使用在用于向服务器发送数据的上下文中传递的相同内容。但是,即使您将其转换为存储在编辑器驱动程序中的上下文类型,从flush返回的上下文也只允许Receiver<Void>。编辑()调用。 [它似乎也没有发送和EntityProxyChanged事件,所以我无法监听并更新显示视图。 - 抓住这个 - 我现在看到此事件不适用于此用例]

我找到的解决方案是更改我的域对象persist以返回新保存的实体。然后像这样创建弹出编辑器

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();

然后在保存处理程序中,我只是触发()从flush()获得的上下文。虽然这种方法有效,但似乎并不正确。 [看起来我应该在显示视图中订阅entitychanged事件并从那里更新实体和视图。 - 再次刮擦,与之前的原因相同]此方法也保存了完整的实体,而不仅仅是更改的位,这将增加带宽使用。

我认为应该发生的事情是,当您刷新实体时,应该“乐观地”更新实体的rf托管版本并触发实体代理更改事件。只有在保存中出现问题时才恢复实体。实际保存只应发送更改的位。通过这种方式,无需重新获取整个实体并通过线路两次发送完整数据。

有更好的解决方案吗?

2 个答案:

答案 0 :(得分:2)

您似乎并不真正理解RF发生的细节;另外,你的术语并没有真正帮助理解(冲洗与火灾)。

RF中的代理是您检索服务器时状态的快照。您可以使用应用程序中其他位置的实体(通过其他代理)执行任何操作,您的代理将不会更改以反映这些修改。

当服务器检测到它已更改时,在客户端(对于服务器已知且已从客户端发送的实体)调度EntityProxyChange事件:其版本(由getVersion上的Locator返回的已更改,或已被删除(由isLive的{​​{1}}方法说明)。如果您不使用Locator,则会使用该实体的LocatorgetVersion将被isLive实体替换为其ID(如已返回)通过find方法)并检查getId(这也是nullisLive的默认实现。) 在您的情况下,如果您没有看到正在调度Locator,请检查您是否正确更新了实体的版本。

最后,RF总是将更改的差异发送到服务器(EntityProxyChange除外,在这种情况下,差异无意义)。至于检索数据,默认情况下它不会检索链接代理,除非您使用ValueProxy明确要求它们;这与您发送的有关实体的内容无关。

在您的情况下,要更新视图面板,您有3种可能性:

  • 从服务器检索代理(收听with事件或弹出窗口中的显式信号;您可以使用代理{{1}的EntityProxyChange find方法作为参数,以及您需要的属性的相应RequestContext 你正在做第二个HTTP请求时效率有点低,但另一方面它可以处理应用程序中其他地方的更改(它们也会触发stableId个事件)
  • 在与用于保存的请求相同的HTTP请求中检索更新的代理:让请求上下文的with方法返回已保存的实体,或者在同一个方法中调用EntityProxyChange方法请求同一HTTP请求中的批处理 savefind的上下文。
    那就是你做的。它发送更改的差异并检索视图面板所需的属性。可以说它具有将弹出窗口和视图面板紧密耦合的缺点,由您来决定它是否是可接受的权衡。
  • 使用您编辑的实体并在视图面板中直接发送到服务器,而无需通过网络获取额外数据 虽然这看起来更简单,但您将错过其他用户可能对该实体进行的任何更改(仅更改服务器知道)。

总而言之,我认为我会选择当前的解决方案。关于你的代码,我将使用代理和回调启动弹出窗口,并将请求上下文和编辑编辑器驱动程序保留为弹出窗口的实现细节:你只需要它调用视图面板完成后,将更新的代理作为参数传递给回调。

关于术语的最后一句话:你刷新编辑器驱动程序将字段的值复制回对象/代理,并且(独立地,但在你的情况下顺序)你 fire 一个请求上下文,用于向服务器发送一批服务方法和代理更改。刷新编辑器驱动程序不会向服务器发送任何内容,这些是不同的操作。

答案 1 :(得分:1)

我找到了更好的解决方案。我在调用RequestFactoryEditorDriver edit()之前使代理可编辑,并将可编辑代理保存为我的视图代理。

PlayerProfileCtx ctx = rf.playerProfile();
playerProfile = ctx.edit(playerProfile);
driver.edit(playerProfile, ctx);

另外,(我以为我之前尝试过这个并且它没有用,但我一定做错了)然后我可以转换从flush回来的上下文。

edit()

这样做解决了rf使用fire()发送整个对象而不仅仅是差异的问题。我不知道为什么会这样。这可能是RF编辑器驱动程序中的错误。

所以现在我已经在视图中获得了驱动程序中的数据,而不必依赖于从服务器发送回来的数据。但我确实注册了EntityProxyChange事件,因此如果服务器上存在冲突,我可以检测并重新获取。