GWT Activities and Places - 如何理解这个概念?
GWT Activities and Places - How to understand this concept?
好的,Activity 建立在 Places 之上。地方是“just URLs”。但是我只是不知道如何正确使用它们..
没有嵌套活动“because YAGNI”;但在这个简单的场景中它看起来如何:
- 有登录页面
- 有一个管理页面,提供以下功能
- 向我的公司添加活动
- 将商品添加到我的商店
成功登录后,网站的 "main container" 将被清除并填充 admin-activity 的新内容。这里必须更改的一件事是 ActivityMapper
的 "display",因为现在我在左侧有一个导航栏,在右侧有一个主要内容 Div。
我可以有一个 LoginActivity
和一个 AdminActivity
。这意味着我会有像
这样的网址
/#LoginPlace:noParams
/#AdminPlace:eventManager
/#AdminPlace:itemManager
但这很愚蠢,恕我直言,因为实际上我想要这样的东西:
/#LoginPlace:noParams
/#AdminPlace:eventManager|storeId=1,langaugeId=2
/#AdminPlace:itemManager|storeId=1,langaugeId=2,page=0
但这需要我的 AdminActivity
分解 URL 并注意所有这些不同类型的 URL,对吧?我的意思是这样的:
private AdministrationActivity administrationActivity;
@Override
public Activity getActivity(Place place) {
if (place instanceof LoginPlace) {
return new LoginActivity((LoginPlace) place);
} else if (place instanceof AdministrationPlace) {
if(this.adminActivity== null) {
this.adminActivity= new AdministrationActivity((AdministrationPlace) place);
} else {
this.adminActivity.updateMainContent(((AdministrationPlace) place).getUrl());
}
return this.adminActivity;
}
return null;
}
现在 adminActivity.updateMainContent()
必须对所有地方进行解析才能显示正确的内容。
这就是解决方案:
/#LoginPlace:noParams
/#EventManagerPlace:storeId=1,langaugeId=2
/#ItemManagerPlace:storeId=1,langaugeId=2,page=0
但是(!) 现在每个地方都需要一个 activity,对吧?而且我只是不确定是否有与活动一样多的地方。我以为一个 activity 可以导航到不同的地方。
那么应该如何使用地点和活动?
我建议您可能希望每个地方有一个 Activity。通常存在粗略的一对一关系,但由于关注点分离,它们会分开,因此您可以在没有 Activity.
的情况下传递一个 Place
遗憾的是,标准 GWT 不支持添加参数。我们基于 UrlBuilder 创建了我们自己的简单的。
此 https://code.google.com/p/google-web-toolkit/issues/detail?id=2422(旧问题跟踪器)存在一个长期存在的问题,其中包含其他想法和链接。
启动后 运行 效果非常好。我喜欢使用强类型对象和 goTo 而不是将 URL 粘在一起。
您要问自己的第一个问题是 "where will the user possibly go?"。据我了解,您至少拥有:
- 事件列表,可能具有 filter/selection 条件和分页属性
- 项目列表,具有可能的 filter/selection 条件和分页属性
也许您还会有像 "details of an event" 这样的地方(如果用户会在两种状态之间切换,甚至可能会在只读详细信息和可编辑详细信息之间进行拆分;如果状态取决于用户是谁,那么这是 IMO 同一个地方,用户可以执行的操作不同),"details of an item"、"form to add an event"、"form to add an item".
对我来说,登录是一个跨领域的功能,它不是用户在您的应用程序中要做的事情(它不是业务用例,不是 "activity" 用户工作的一部分) .不过,您仍然可以选择使用地点和 activity 进行登录;所以让我们将其添加到列表中:"login form"(我绝对不会这样做,但那是另一回事了)。
现在您可以选择如何将这些地点表示为 GWT Place
对象:您可以有一个 Place
子类,其中 属性 告诉您确切的 "place" 你在(基本上是你的 AdminPlace:eventManager
令牌建议的),或者每个 "place" 一个 Place
子类(你的 EventManagerPlace
令牌建议的)。这完全独立于您是否有一项或多项活动。
下一个问题是关于屏幕的各个区域,这将映射到 ActivityManager
s:导航时屏幕的哪些部分会发生变化?也许它们不会同时/在相同条件下都发生变化。
因此,例如,您的导航栏是否应该在 activity 内?如果你可以把它放在外面(因为它被重复使用),那就去做吧。如果它始终相同(对 selected 项取模),它实际上什至不需要是 activity。在任何情况下,使它成为一个单例(或类似的)并听 PlaceChangeEvent
s 到 select 适当的项目(不一定是 "singleton",但至少不是在每次导航时重新创建)。将导航栏放在活动之外的好处是,如果你最终决定让它垂直而不是水平(或相反),and/or 可折叠,你将不必改变你的活动(分离忧虑)。如果您必须构建一个移动应用程序,您甚至可以在该应用程序上放置一个 "menu" 位置来显示导航栏整页并在导航时将其交换为其他活动。
所以我们现在有 2 个 显示区域 ,即 2 个 ActivityManager
及其各自的 ActivityMapper
。或者可能只有一个 显示区域 用于 "main content",并且导航栏不是 Activity。下一步是准确确定更改的内容和时间;即,当我去 X 地点时,我需要在那个区域放那个东西,在那个地方放另一个东西;那些 "things" 是你的活动。
"model" 活动的关键是考虑用户所做的事情(活动)并专注于其中一项。但活动也与用户如何与应用程序交互和导航相关(例如,添加项目时,表单是否出现在列表上方的弹出窗口中,或替换列表);所以如果你想真正完全分离关注点,你可能会创建一些对象来管理 events/items 的列表,并有一个非常薄的 Activity 只实例化和管理该对象。不过,作为起点,这可能是过度设计的,如果您觉得需要的话,稍后将它从 Activity 中排除出来会相对容易。
我喜欢(这基本上就是该功能的设计方式)具有 一次性 活动。在我的 ActivityMapper
中,Activity 需要知道的 Place
中的所有内容都传递给了它的构造函数; Activity 不必知道当前位置(或监听位置变化),并且 ActivityMapper
也不是 "mutated"。由于各种原因,当然也有例外。如果您需要在 "places" 之间共享给定 activity 的状态(例如数据缓存等),您不一定要重用它,您可以通过共享有状态对象共享状态并保留activity 大部分是无国籍人。
无论如何,你认为一个大 AdminActivity
本身根据当前位置交换其大部分内容的想法类似于嵌套。
最后,没有万能的,您必须尝试选择最适合您需求的策略。
最后但同样重要的是,不要使用需要 解析 的通用 getUrl()
来设计您的位置;解析你 PlaceTokenizer
中的 一切 ;分词器不需要知道这个地方在你的 URL 中的样子(而且你甚至不会被迫使用 PlaceHistoryHandler
开始,所以你的地方甚至可能永远不会结束在 URL – 你的位置将无法添加书签,你将无法通过浏览器历史记录在应用程序中导航)
关键概念是关注点分离。
好的,Activity 建立在 Places 之上。地方是“just URLs”。但是我只是不知道如何正确使用它们..
没有嵌套活动“because YAGNI”;但在这个简单的场景中它看起来如何:
- 有登录页面
- 有一个管理页面,提供以下功能
- 向我的公司添加活动
- 将商品添加到我的商店
成功登录后,网站的 "main container" 将被清除并填充 admin-activity 的新内容。这里必须更改的一件事是 ActivityMapper
的 "display",因为现在我在左侧有一个导航栏,在右侧有一个主要内容 Div。
我可以有一个 LoginActivity
和一个 AdminActivity
。这意味着我会有像
/#LoginPlace:noParams
/#AdminPlace:eventManager
/#AdminPlace:itemManager
但这很愚蠢,恕我直言,因为实际上我想要这样的东西:
/#LoginPlace:noParams
/#AdminPlace:eventManager|storeId=1,langaugeId=2
/#AdminPlace:itemManager|storeId=1,langaugeId=2,page=0
但这需要我的 AdminActivity
分解 URL 并注意所有这些不同类型的 URL,对吧?我的意思是这样的:
private AdministrationActivity administrationActivity;
@Override
public Activity getActivity(Place place) {
if (place instanceof LoginPlace) {
return new LoginActivity((LoginPlace) place);
} else if (place instanceof AdministrationPlace) {
if(this.adminActivity== null) {
this.adminActivity= new AdministrationActivity((AdministrationPlace) place);
} else {
this.adminActivity.updateMainContent(((AdministrationPlace) place).getUrl());
}
return this.adminActivity;
}
return null;
}
现在 adminActivity.updateMainContent()
必须对所有地方进行解析才能显示正确的内容。
这就是解决方案:
/#LoginPlace:noParams
/#EventManagerPlace:storeId=1,langaugeId=2
/#ItemManagerPlace:storeId=1,langaugeId=2,page=0
但是(!) 现在每个地方都需要一个 activity,对吧?而且我只是不确定是否有与活动一样多的地方。我以为一个 activity 可以导航到不同的地方。
那么应该如何使用地点和活动?
我建议您可能希望每个地方有一个 Activity。通常存在粗略的一对一关系,但由于关注点分离,它们会分开,因此您可以在没有 Activity.
的情况下传递一个 Place遗憾的是,标准 GWT 不支持添加参数。我们基于 UrlBuilder 创建了我们自己的简单的。
此 https://code.google.com/p/google-web-toolkit/issues/detail?id=2422(旧问题跟踪器)存在一个长期存在的问题,其中包含其他想法和链接。
启动后 运行 效果非常好。我喜欢使用强类型对象和 goTo 而不是将 URL 粘在一起。
您要问自己的第一个问题是 "where will the user possibly go?"。据我了解,您至少拥有:
- 事件列表,可能具有 filter/selection 条件和分页属性
- 项目列表,具有可能的 filter/selection 条件和分页属性
也许您还会有像 "details of an event" 这样的地方(如果用户会在两种状态之间切换,甚至可能会在只读详细信息和可编辑详细信息之间进行拆分;如果状态取决于用户是谁,那么这是 IMO 同一个地方,用户可以执行的操作不同),"details of an item"、"form to add an event"、"form to add an item".
对我来说,登录是一个跨领域的功能,它不是用户在您的应用程序中要做的事情(它不是业务用例,不是 "activity" 用户工作的一部分) .不过,您仍然可以选择使用地点和 activity 进行登录;所以让我们将其添加到列表中:"login form"(我绝对不会这样做,但那是另一回事了)。
现在您可以选择如何将这些地点表示为 GWT Place
对象:您可以有一个 Place
子类,其中 属性 告诉您确切的 "place" 你在(基本上是你的 AdminPlace:eventManager
令牌建议的),或者每个 "place" 一个 Place
子类(你的 EventManagerPlace
令牌建议的)。这完全独立于您是否有一项或多项活动。
下一个问题是关于屏幕的各个区域,这将映射到 ActivityManager
s:导航时屏幕的哪些部分会发生变化?也许它们不会同时/在相同条件下都发生变化。
因此,例如,您的导航栏是否应该在 activity 内?如果你可以把它放在外面(因为它被重复使用),那就去做吧。如果它始终相同(对 selected 项取模),它实际上什至不需要是 activity。在任何情况下,使它成为一个单例(或类似的)并听 PlaceChangeEvent
s 到 select 适当的项目(不一定是 "singleton",但至少不是在每次导航时重新创建)。将导航栏放在活动之外的好处是,如果你最终决定让它垂直而不是水平(或相反),and/or 可折叠,你将不必改变你的活动(分离忧虑)。如果您必须构建一个移动应用程序,您甚至可以在该应用程序上放置一个 "menu" 位置来显示导航栏整页并在导航时将其交换为其他活动。
所以我们现在有 2 个 显示区域 ,即 2 个 ActivityManager
及其各自的 ActivityMapper
。或者可能只有一个 显示区域 用于 "main content",并且导航栏不是 Activity。下一步是准确确定更改的内容和时间;即,当我去 X 地点时,我需要在那个区域放那个东西,在那个地方放另一个东西;那些 "things" 是你的活动。
"model" 活动的关键是考虑用户所做的事情(活动)并专注于其中一项。但活动也与用户如何与应用程序交互和导航相关(例如,添加项目时,表单是否出现在列表上方的弹出窗口中,或替换列表);所以如果你想真正完全分离关注点,你可能会创建一些对象来管理 events/items 的列表,并有一个非常薄的 Activity 只实例化和管理该对象。不过,作为起点,这可能是过度设计的,如果您觉得需要的话,稍后将它从 Activity 中排除出来会相对容易。
我喜欢(这基本上就是该功能的设计方式)具有 一次性 活动。在我的 ActivityMapper
中,Activity 需要知道的 Place
中的所有内容都传递给了它的构造函数; Activity 不必知道当前位置(或监听位置变化),并且 ActivityMapper
也不是 "mutated"。由于各种原因,当然也有例外。如果您需要在 "places" 之间共享给定 activity 的状态(例如数据缓存等),您不一定要重用它,您可以通过共享有状态对象共享状态并保留activity 大部分是无国籍人。
无论如何,你认为一个大 AdminActivity
本身根据当前位置交换其大部分内容的想法类似于嵌套。
最后,没有万能的,您必须尝试选择最适合您需求的策略。
最后但同样重要的是,不要使用需要 解析 的通用 getUrl()
来设计您的位置;解析你 PlaceTokenizer
中的 一切 ;分词器不需要知道这个地方在你的 URL 中的样子(而且你甚至不会被迫使用 PlaceHistoryHandler
开始,所以你的地方甚至可能永远不会结束在 URL – 你的位置将无法添加书签,你将无法通过浏览器历史记录在应用程序中导航)
关键概念是关注点分离。