【问题标题】:GWT MVP updating Activity state on Place changeGWT MVP 在 Place 更改时更新 Activity 状态
【发布时间】:2013-03-09 03:59:54
【问题描述】:

在地点更改时更新 Activity 状态的最佳做法是什么?假设您有一个带有视图的活动,该视图显示类别列表和类别中的项目列表。如果选择了不同的类别,则应用程序将使用类别 ID 转到新位置。然后我想只刷新项目,而不是创建也重新读取类别列表的新活动。

我目前的做法是这样的:

public class AppActivityMapper implements ActivityMapper {

    private ItemListActivity itemListActivity;

    ...

    public Activity getActivity(final Place place) {
        final Activity activity;

        if (place instanceof ItemListPlace) {
            if (itemListActivity == null) {
                itemListActivity = new ItemListActivity((ItemListPlace) place, clientFactory);
            } else {
                itemListActivity.refresh((ItemListPlace) place);
            }
            activity = itemListActivity;
        } else {
            itemListActivity = null;
        }

        ...
        return activity;
    }

    ...

【问题讨论】:

    标签: gwt mvp gwt-mvp gwt-places gwt-activities


    【解决方案1】:

    替代方案是:

    • 在活动中收听PlaceChangeEvents(然后您可以使用FilteredActivityMapperCachingActivityMapper缓存您的ActivityMapper 中的活动,以便它被简化为仅在被询问时创建一个新活动)。 †

    • 让一些组件监听PlaceChangeEvents 并将它们翻译到面向业务的事件,然后活动监听这些事件而不是PlaceChangeEvents,否则同上.

    • 将活动与“屏幕”分离,使用reset() 方法使“屏幕”成为单例,并从活动的start 调用该方法(在这种情况下可能将类别ID 作为参数传递) )。作为单例的“屏幕”可以确保只加载一次类别列表。

    • 在您的情况下,您也可以简单地将类别列表放在共享缓存中,这样您就不必通过创建新的活动来重用您的活动,类别列表将被检索一次并放入在缓存中,后续活动实例将只使用缓存中的内容。这与上面类似,但更简单,缓存可以被应用程序的其他部分使用。

    不过,我个人更愿意采用您的方法(有一个小例外,见下文),因为它是最简单/最容易的。将活动与“屏幕”分离也是一种选择; GWT 团队开始在 Expenses 示例中探索这种方法(使用 MVP 将活动责任与演示者责任分离),但遗憾的是没有完成。

    除此之外,我认为目前还没有真正出现任何最佳实践


    †。我不喜欢将我的活动与它们使用的地方结合起来(我也不太喜欢 goTo 调用的结合,但还没有找到一个干净简单的替代方案),所以我会而不是选择这个选项;同样,我不会像您那样将位置传递给活动构造函数和refresh 方法,而是从该位置提取信息并将其传递给活动(例如,在您的情况下,仅将类别 ID 提供给活动,而不是 ItemListPlace 实例;然后我会在所有情况下都简单地调用 setCategory,甚至不将类别 ID 传递给构造函数。

    【讨论】:

      【解决方案2】:

      在我看来,

      • ActivityMapper 的作用是从Place 中返回Activity
      • ActivityManager 的作用是启动从ActivityMapper 返回的Activity,如果不同则停止当前的。在您的情况下,您想“更新/刷新”当前的Activity

      所以我会修改ActivityMapper,这样对于给定类型的Place,它总是会返回相同的Activity 实例。这样做的一个好方法是使用 GIN 并使用单例范围 ...in(Singleton.class) 注入您的 Activity

      如果您这样做,在更改 url 时,如果地点保持不变(意味着您的 url 在 # 之后和之前 :) 具有相同的单词,因此您的地点的类型保持不变,ActivityMapper 将给出你支持Activity 的同一个实例,所以ActivityManager 不会对Activity 执行任何操作。检查ActivityManager的l.126

      if (currentActivity.equals(nextActivity)) {
        return;
      }
      

      对我来说,你有 2 个选项。第一个,正如托马斯所说,是在你的Activity 中收听PlaceChangeEvent。您将收到的新Place 可以根据给定的新网址在内部包含新参数,并且您可以“更新/刷新”您的Activity

      我发现第二个更符合 Activity/Place 模式的方法是修改 ActivityManager,以便当 ActivityActivityMapper 与当前的Activity 相同。

      我还没有尝试过任何这些解决方案,但我很快就会......我可能能够在那个时候更新那个帖子。

      You can find more information in this article I wrote on my blog on that topic

      这是我为帮助我理解模式而制作的一个小架构,希望对您有所帮助:

      【讨论】:

      • 您是否尝试过第二种解决方案?效果如何?或者您是否找到了更好的方法?
      • 抱歉没有。 :( Nerver 确实需要。我们只需使用新参数重新加载活动。
      • 好的。我只是在尝试Marting正在做的事情。我不确定这是否可以扩展,但我要问它place instanceof MainActivity,如果是这样并且不为空,我只需调用mainActivity.updateMainContent(place.getCurrentPlaceToken()),以便在单击菜单中的按钮后更新主要内容。感觉只是更新主要内容的开销很大,但确实如此..
      【解决方案3】:

      我不会在我的 ActiviyMapper 中执行任何逻辑,除了返回一个活动,通过创建一个新活动或提供前一个活动(或 null)。据我说,映射器不必知道 refresh() 或活动的作用。

      如果是这样,那么'refresh()'的逻辑将通过持有令牌的地方赋予活动。该令牌应该包含有关请求状态的信息(新页面、重新加载、ID 等)。

      在活动中,首先,它请求视图,与此活动相关的视图(提示:由“ClientFactory”提供的单例是很好的做法),然后它为该视图创建一个演示者,并将它们绑定在一起.

      最后,活动将使用该地点的令牌向演示者提供有关状态的任何信息。然后,它在页面中添加视图。

      很高兴知道默认情况下,对于地点和活动,去同一个地方不会做任何事情(不重新加载)。但是您可以使用令牌和活动映射器轻松处理它。

      希望您能找到适合您的情况的解决方案。祝你好运。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-19
        • 1970-01-01
        • 2018-05-21
        • 1970-01-01
        • 2016-10-21
        • 2020-09-28
        相关资源
        最近更新 更多