我有一个使用活动和地点的GWT MVP应用程序。这是受到Mauro Bertapelle的样本(this thread)的启发,显然基于Thomas Broyer的一些工作。
问题在于:我让LoginActivity进行RPC调用,为了成功登录,返回一个User。该用户具有角色(例如,管理员,普通用户,访客)。包括NavigatorView在内的多个视图和活动依赖于此角色来显示或执行的操作。如何将此User实例提供给其他活动?
我没有ClientFactory; inject(Gin)用于实例化ActivityProviders中提供我的Activities / Presenters的Views,并将ActivityProviders注入到我的ActivityMapper中。所以这可能会减少到一个杜松子酒问题:如何在需要的地方获得用户参考?这似乎与this SO question类似,关于MVP中的全局引用。
考虑我一个杜松子酒新手,这是我第一次尝试使用它。我猜测有一种“杜松子酒方式”可以实现这一点,但我不知道杜松子酒能够知道最好的方法(如果应该使用杜松子酒)。
非常感谢。
编辑1:尽管我在搜索SO以寻找类似问题时尽了最大的努力,但我发现this question与我的几乎完全相同(是用于查找“相关”链接的SO算法比搜索更好?)。我认为David的Gin回答是正确的。
我不认为EventBus解决方案是可行的。我正在关注Google guidelines,其中涉及在每次Place更改时实例化Activity,因此单个事件本身是不够的。
答案 0 :(得分:3)
我在服务器端与Guice一起使用的东西,在客户端也能正常工作,就是绑定到自定义Provider。但是,在您的情况下,您必须使提供程序成为单例并从RPC回调中将值推入其中(而不是从某些上下文中提取它)。 您首先需要一个特定的提供者:
@Singleton
public class CurrentUserProvider implements Provider<User> {
private User currentUser;
public User get() { return currentUser; }
public void setCurrentValue(User currentUser) {
this.currentUser = currentUser;
}
}
您将User
绑定到提供商:bind(User.class).toProvider(CurrentUserProvider.class)
在您的RPC回调中,您将注入一个CurrentUserProvider
,因此您可以setCurrentValue
,但在其他任何地方注入Provider<User>
以保留CurrentUserProvider
作为实施细节。对于非常短暂的对象,您可以直接注入User
值而不是Provider<User>
。
如果您需要通知对象更改值,您可以在全局事件总线上调度事件。
或者,您可以始终使用具体的CurrentUserProvider
类型(不再需要实现Provider
)并可能使其成为HasValueChangeHandlers
,以便您可以在其上注册侦听器而不是在事件总线上(但你必须在你的活动'onStop
和onCancel
之后清理自己,以避免内存泄漏,而如果你在事件上注册处理程序,它会自动处理onStart
)中的公共汽车。
(如果你问我,我宁愿尽可能在应用程序内部进行身份验证)
答案 1 :(得分:1)
我对最近的一个项目有类似的要求。
当我从登录(或注销)RPC获得回复时,我在EventBus上发送自定义AuthenticationEvent。所有对此感兴趣的活动都会收听此活动。 AuthenticationEvent具有对AppUser对象的引用,如果用户刚刚注销,则该引用为null。 AppUser包含所有必要的数据(特权,组等),以便活动可以检查它并对其采取行动。
关于全局引用:您可以使用提供所需数据的静态方法的类。此类在内部保存对所需实例的单例引用。在我的例子中,我有静态方法AppUtils.getCurrentUser()。在内部,它包含对AppUser的引用,并且还侦听AuthenticationEvent以设置/重置此字段。
作为旁注:不要依赖客户端来强制执行访问限制 - 您应该将RPC servlet分成两组:public和private。公共可以被任何人访问(这基本上是登录/注销RPC和一些其他公共信息RPC),而私有RPC要求用户进行身份验证。可以为每个路径/ servlet设置访问限制:http://code.google.com/appengine/docs/java/config/webxml.html#Security_and_Authentication
<强>更新强>
正如您所指出的,在此设置中不建议使用静态方法的类,因为它不可替换,这会阻止测试(这是使用GIN的重点)。
解决方案是将一个包含全局变量(AppUtils)的实用程序类注入需要全局变量的活动中。 AppUtils应该在GIN配置中声明为singleton,因为一个实例足以满足整个应用程序。
如果您想延迟依赖项的初始化(AppUtil是依赖项),那么使用Provider
只是一个问题。由于AppUtils是整个应用程序的单例,因此将其初始化为懒惰是没有意义的。
有时你会遇到屏幕上显示多个活动的情况(在我的例子中是MenuBar和InfoBar)。在这种情况下,当用户登录时,您需要一种方法来通知他们更改。使用EventBus。