Должны ли действия/места GWT быть синглтонами или прототипами?

В чем разница (производительность и прочее) между этим:

public class MyPlaceMapper implements PlaceHistoryMapper {
    @Override
    public String getToken(Place place) {
        if(place instanceof HomePlace)
            return "home";
        else
            return null;
    }

    @Override
    public Place getPlace(String token) {
        if(token.equals("home"))
            return new HomePlace();
        else
            return null;
    }
}

А также:

public class MyPlaceMapper implements PlaceHistoryMapper {
    // Singleton HomePlace to inject and reuse over and over again
    private HomePlace homePlace;

    // Getter/setter for homePlace...

    @Override
    public String getToken(Place place) {
        if(place instanceof HomePlace)
            return "home";
        else
            return null;
    }

    @Override
    public Place getPlace(String token) {
        if(token.equals("home"))
            return homePlace;
        else
            return null;
    }
}

Другими словами, какая разница, буду ли я повторно использовать один и тот же «синглтон» Place снова и снова, или я просто создаю новый экземпляр каждый раз, когда он запрашивается.

Кроме того, тот же вопрос для Activitys изнутри ActivityMapper. Спасибо еще раз!


person Community    schedule 23.11.2012    source источник
comment
Спасибо, @SergeyVedernikov, но ваш комментарий мне не очень помогает. Он не дает никакого объяснения различий между этими стратегиями. Я спрашиваю, потому что Activity можно запускать и останавливать, а несколько Places одного и того же класса могут запускаться в EventBus, и мне интересно, как это повлияет на одновременную работу нескольких прототипов этих классов.   -  person    schedule 23.11.2012
comment
Ok. Когда вы создаете новый объект Place и возвращаете этот объект в getPlace, этот объект будет удален из памяти после остановки Activity. По деятельности такая же ситуация. Но если вы будете хранить все эти объекты в мапперах, вы будете использовать больше клиентской памяти. В то время как места — это маленькие объекты, действия могут быть огромными. Надеюсь, мое объяснение понятно :)   -  person Sergey Vedernikov    schedule 23.11.2012


Ответы (2)


Эмпирическое правило: места должны быть неизменными. Имея это в виду, использовать одноэлементное место можно только в том случае, если к месту не привязаны данные (как в вашем примере HomePlace). Поскольку места настолько легковесны, последствия использования синглтона по сравнению с созданием нового экземпляра незначительны.

Совсем другая история с действиями, потому что они не являются объектами-ценностями.

Что означает использование одноэлементной активности?

  • вы должны очистить состояние в onStop и onCancel, иначе состояние от предыдущего использования действия может просочиться в более позднее его использование. Хотя в некоторых случаях это полезно, я думаю, что лучше оставить поведение кеширования отдельным (разделение задач).
  • синглтоны по определению хранятся в памяти на протяжении всего жизненного цикла приложения, даже те, которые пользователь увидит/использует только один раз. Например, экран приветствия в Google Groups, скорее всего, будет показан только один раз за запуск приложения, так зачем хранить его в памяти?
  • если вы перемещаетесь между двумя местами, которые оба сопоставляются с одной и той же активностью, активность не будет перезапущена (это особенность ActivityMapper), поэтому вам нужно как-то сигнализировать активности, что место изменилось (при необходимости, конечно ). Это можно сделать в ActivityMapper или заставить активность прослушивать PlaceChangeEvents.

Если вы используете MVP (отделение представления от действия), действия, как правило, невелики, поэтому использование краткосрочных освобождает вас от вышеперечисленного убедитесь, что вы очистили все в onStop и onCancel и сообщить активности, что место изменилось, и в целом все упрощается: активность создается, затем запускается, затем отменяется или останавливается, и она исчезает, готовая к сборке мусора. Если вам нужно хранить в кеше некоторые данные или результаты вычислений, используйте явный объект кеша, который будет совместно использоваться всеми экземплярами вашей активности; это проясняет ситуацию.


Небольшое примечание о MVP и жизненном цикле представлений: представления (виджеты), как правило, тяжеловесны, поэтому для часто используемых можно сделать их синглтонами. В этом случае ваша активность должна будет очищать состояние представления (значения полей и т. д.) в своем методе start (или, возможно, onStop и onCancel), каким-то образом побеждая использование краткосрочных действий. кэширование представления (вы можете не использовать один элемент, а хранить экземпляр в памяти в течение некоторого времени и удалять его после некоторой задержки) следует рассматривать как оптимизацию здесь, где создание нового представления стоит намного больше, чем его очистка при запуске активности. Это компромисс.

Мой подход к MVP заключается в том, что представление не имеет состояния само по себе, то есть докладчик действительно контролирует то, что представление должно отображать/знать/и т. д. поэтому очистка представления start является частью потока: ведущий (во многих случаях действие) знает, в каком состоянии оно находится, и отражает это состояние в представлении; а start — это время, когда ему передается управление представлением. Этот подход был описан Google при создании Wave во время Google I/O 2010 в Рекомендации по тестированию GWT.

person Thomas Broyer    schedule 23.11.2012

Отличный ответ Томаса. Просто чтобы добавить еще немного информации.

Вы можете решить переопределить реализацию объектов по умолчанию, заданную Google. Например, вы можете написать свой собственный картограф активности, который всегда будет возвращать один и тот же экземпляр активности для данного типа места. Как сказал Томас, это место на самом деле не является важным объектом. Имеет значение действие, связанное с этим местом через картограф действий. Тем не менее, у вас могут возникнуть проблемы с жизненным циклом, и кодирование методов запуска и остановки будет очень сложным.

Возможно, вы захотите перекодировать диспетчер активности и добавить в шаблон метод обновления, чтобы обновить существующую активность, если это то, что вы хотите сделать.

Спросите себя, как ваше приложение должно вести себя при нажатии вперед или назад в браузере. Вы можете найти более подробную информацию в статье, которую я написал о мероприятиях и местах. здесь.

Надеюсь, это поможет.

person Ronan Quillevere    schedule 08.03.2013