简体   繁体   English

GWT MVP更新地方变更的活动状态

[英]GWT MVP updating Activity state on Place change

What is the best practise to update Activity state on Place change? 在地方变更上更新活动状态的最佳做法是什么? Imagine you have an activity with view that displays list of categories and list of items in the category. 想象一下,您有一个带有视图的活动,该活动显示类别列表和类别中的项目列表。 If different category is selected then app goes to new place with category ID. 如果选择了不同的类别,则应用程序将转到具有类别ID的新位置。 I want then to only refresh items and not to create new activity that also re-reads category list. 我想要只刷新项目,而不是创建也重新读取类别列表的新活动。

My current approach is like this: 我目前的做法是这样的:

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;
    }

    ...

Alternatives are: 替代方案是:

  • listen to PlaceChangeEvent s from within the activity (you can then use a FilteredActivityMapper and CachingActivityMapper for the caching of the activity in your ActivityMapper , so that it's reduced to only create a new activity when asked). 从活动中监听PlaceChangeEvent (然后您可以使用FilteredActivityMapperCachingActivityMapper缓存 ActivityMapper中的ActivityMapper ,这样它就会被简化为仅在被询问时创建新活动)。

  • have some component listen to PlaceChangeEvent s and translate them to business-oriented events, the activity then listens to those events rather than PlaceChangeEvent s, otherwise the same as above. 有一些组件听PlaceChangeEvent S和把它们翻译成面向企业的活动,活动然后侦听到这些事件,而不是PlaceChangeEvent S,否则上面一样。

  • decouple the activity from the "screen", make the "screen" a singleton with a reset() method and call that method from the activity's start (possibly passing the category ID as an argument in this case). 将活动与“屏幕”分离,使用reset()方法使“屏幕”成为单例并从活动的start调用该方法(在这种情况下可能将类别ID作为参数传递)。 The "screen" being a singleton could then make sure to load the categories list only once. 然后,作为单身人士的“屏幕”可以确保仅加载类别列表一次。

  • in your case, you could also simply put the categories list in a shared cache, so that you don't have to reuse your activity by can create a new one, the categories list will be retrieved once and put in the cache, subsequent activity instances will just use what's in the cache. 在您的情况下,您还可以简单地将类别列表放在共享缓存中,这样您就不必重新使用您的活动,可以创建一个新的,类别列表将被检索一次并放入缓存,后续活动实例将只使用缓存中的内容。 This is similar to the above, but simpler, and the cache could be used by other parts of the application. 这与上面的类似,但更简单,缓存可以由应用程序的其他部分使用。

I'd personally rather go with your approach though (with a small exception, see below), as it's the simplest/easiest. 我个人宁愿选择你的方法(有一个小例外,见下文),因为它是最简单/最简单的。 Decoupling the activity from the "screen" is also an option; 将活动与“屏幕”分离也是一种选择; the GWT Team started exploring this approach in the Expenses sample (decoupling the activity responsibility from the presenter responsibility with using MVP) without ever finishing it unfortunately. GWT团队开始在费用样本中探索这种方法(将活动责任与主持人责任与使用MVP分离),而不幸地完成它。

Other than that, I don't think any best practice has really emerged for now. 除此之外,我认为现在还没有出现任何最佳实践


†. †。 I don't like coupling my activities with the places they're used with (I don't quite like the coupling for the goTo calls either, but haven't yet found a clean and simple alternative), so I'd rather not go with this option; 我不喜欢将我的活动与他们使用的地方联系起来(我不太喜欢goTo调用的耦合,但还没有找到一个干净简单的选择),所以我宁愿不选择这个选项; and similarly, I'd not pass the place to the activity constructor and refresh method like you did, but rather extract the information out of the place and pass it to the activity (eg in your case, only give the category ID to the activity, not the ItemListPlace instance; I would then simply call setCategory in all cases, and not even pass the category ID to the constructor). 同样地,我不会像你那样将地点传递给活动构造函数和refresh方法,而是将信息提取出来并将其传递给活动(例如,在您的情况下,只将类别ID提供给活动而不是ItemListPlace实例;我会在所有情况下简单地调用setCategory ,甚至不将类别ID传递给构造函数)。

In my opinion, 在我看来,

  • The role of the ActivityMapper is to give you back an Activity from a Place . ActivityMapper的作用是从一个Place返回一个Activity
  • The role of the ActivityManager is to start the Activity given back from the ActivityMapper and to stop the current one if different. ActivityManager的作用是启动从Activity返回的ActivityMapper ,如果不同则停止当前的ActivityMapper In your case you would like to "update/refresh" the current Activity . 在您的情况下,您想“更新/刷新”当前Activity

So I would modify the ActivityMapper so as it will allways give me back the same instance of Activity for a given type of Place . 所以我会修改ActivityMapper ,因为它总是会给我一个给定类型的Place的相同的Activity实例。 A good way to do so could be to use GIN and use the singleton scope ...in(Singleton.class) to inject your Activity . 一个好方法可能是使用GIN并使用单例范围...in(Singleton.class)来注入您的Activity

If you do that, when changing the url, if the place stays the same (meaning your url has the same word after # and before :) so that the Type of your place stays the same, the ActivityMapper will give you back the same instance of Activity so the ActivityManager will do nothing on the Activity . 如果你这样做,在更改url时,如果该地方保持不变(意味着你的url在#之前和之前有相同的单词:),以便你的地方类型保持不变, ActivityMapper将返回相同的实例的Activity所以ActivityManager会做的任何Activity Check l.126 of ActivityManager 检查ActivityManager l.126

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

For me you have 2 options there. 对我来说,你有2个选择。 The first one, as Thomas said , is to listen to PlaceChangeEvent in your Activity . 正如托马斯所说,第一个是在你的Activity PlaceChangeEvent The new Place you will receive can have new parameters inside based on the new url given and you can "update/refresh" your Activity . 您将收到的新Place可以根据给定的新网址内置新参数,您可以“更新/刷新”您的Activity

The second one, that I find more in line with the Activity/Place pattern is to modify the ActivityManager so that it calls an update(Place) method on the Activity when the Activity given back by the ActivityMapper is the same that the current Activity . 第二个,我发现更符合活动/地点图案线是修改ActivityManager使得它调用在一个更新(地点)方法Activity时的Activity由给定的回ActivityMapper是相同的,当前的Activity

I haven't tried any of these solutions yet but I will soon ... I might be able to update that post at that time. 我还没有尝试过任何这些解决方案,但我很快......我当时可以更新那篇文章。

You can find more information in this article I wrote on my blog on that topic 您可以在我在我的博客上写的关于该主题的文章中找到更多信息

Here is a little schema I made to help me understand the pattern, hope it will help : 这是我用来帮助我理解模式的一个小模式,希望它会有所帮助:

在此输入图像描述

I would not do any logic in my ActiviyMapper except returning an activity, by creating a new one or giving a previous one (or null). 我不会在我的ActiviyMapper中做任何逻辑,除了返回一个活动,通过创建一个新的或给一个前一个(或null)。 According to me, the mapper doesn't have to know about refresh() or what activities do. 根据我的说法,映射器不必了解refresh()或活动。

If that, then the logic of 'refresh()' would be given to the activy through the place which holds a token. 如果是这样,那么'refresh()'的逻辑将通过持有令牌的地方给予活动。 That token should be holding the information about either what is the state of the request (a new page, reload, an id, etc). 该令牌应该包含有关请求状态(新页面,重新加载,ID等)的信息。

In the activity, first, it asks for the View, the one related to this activity (tip : a singleton given by a 'ClientFactory' is good practice), then it creates a presenter for that view, and bind them together. 在活动中,首先,它要求View,与此活动相关的一个(提示:'ClientFactory'给出的单例是一个好习惯),然后它为该视图创建一个演示者,并将它们绑定在一起。

Lastly, the activity will use the token from the place to provide any information about state to the presenter. 最后,活动将使用该地点的令牌向演示者提供有关状态的任何信息。 And then, it adds the view in the page. 然后,它在页面中添加视图。

It's good to know by default, with places and activies, going to the same place doesn't do anything (no reload). 默认情况下,通过地点和活动,去同一个地方不做任何事情(没有重新加载)是很好的。 But you can take care of it with token and activity-mapper easily. 但您可以轻松地使用令牌和活动映射器来处理它。

Hope you'll find an adapted solution for you case. 希望您能找到适合您的解决方案。 Goodluck. 祝好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM