3

我正在使用我继承的大型应用程序,并且遇到了一些最佳实践问题。

每次用户导航到我们的客户编辑页面时,都会创建一个新的演示者,并设置一个视图。有一个用于客户编辑的主演示者和一个主视图。主视图中也有由主演示者的子演示者使用的子视图。在子演示者中,我在事件总线上注册事件处理程序。

我遇到的问题是,当第二次导航到联系人编辑器时,会再次创建演示者,并再次注册这些事件。现在,当一个事件发生时,它会被处理两次,每个演示者实例一次。

演示者不受变量的约束,但子视图由主视图引用。难道是视图中的这个引用阻止了事件处理程序被删除?我的印象是,如果该对象被垃圾收集,事件处理程序将被删除。如果不是这种情况,我是否应该从事件总线中注销这些事件处理程序?

更新:演示者没有被垃圾收集。如果我可以修改代码以在不再需要这些演示者时删除对这些演示者的所有引用,它们是否会被收集,因此事件处理程序是否会被删除?

4

2 回答 2

5

ResettableEventBus是专门为此设计的 - 不是给 Presenter 一个全局事件总线,而是将该事件总线包装在 Resettable 版本中。然后,当该演示者关闭时,给它事件总线的人将重置它,从而清除它可能添加的所有处理程序。

这就是如何管理 GWT 的 Activity/Place 框架中的活动以防止它们泄漏。

另一种选择 - 给每个 Presenter 一个类似 'stop()' 或 'release()' 的方法,表明它是最重要的,它应该在自己之后清理 - 取消正在进行的 RPC 调用,删除对话框,取消事件处理程序。和上面一样,Activity api 有一个方法来指示它即将停止,并且它已经停止并且应该清理。

提供这两者可以很容易地避免在全局事件总线上出错,并且仍然为更细粒度的问题(长时间运行的 RPC 调用)提供了一个挂钩,但问题可以通过任何一种解决方案来解决。

于 2012-12-06T23:28:07.947 回答
1

事件处理程序是独立的对象实例,它们针对 EventBus 内的某种集合进行设置和存储。您的演示者只是创建它们并将它们传递给 EventBus,因此在演示者的生命周期之外仍然会引用处理程序(这就是它们继续运行的原因)。演示者可能没有被垃圾收集,因为处理程序可能仍然引用它们或它们的字段。

每次创建新的演示者时都会再次添加处理程序,因此解决方案是在实例化新的演示者之前清除现有的处理程序,或者跟踪它们而不是在已经添加新的处理程序时添加.

我采取的方法是重用屏幕级别的 View/Presenter 实例并在重新进入时重置它们的状态。这也有助于提高性能。演示者还跟踪他们添加到 EventBus 的所有处理程序的 HandlerRegistration 实例。

我不知道 Colin 提到的 ResettableEventBus,但这听起来也是一个很好的解决方案。

于 2012-12-06T23:49:23.493 回答