Является ли нормой практика иметь член ClientBundle в содержащем ClientBundle?

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

Мой вопрос: так как MyAppResources является одиночным (это не обязательно должно быть, как упоминалось в других постах), но CellTableResources нет, и CellTableResources является членом этого экземпляра, который также расширяет интерфейс ClientBundleБудет ли прокси "CellTableResources" создаваться на каждом MyAppResources.INSTANCE.cellTableResources().foo()?

Если так, могу ли я создать MyAppResources.CELLTABLE_RESOURCE_INSTANCE обойти это? Или создание прокси будет незначительным, даже если есть многочисленные призывы к MyAppResources.INSTANCE.cellTableResources().#?

Во-вторых, еще вопрос для обсуждения: что является наилучшей практикой в ​​отношении использования нескольких ClientBundleв этом случае? Должен ли я вместо этого использовать CellTableResources отдельно (удалите его из MyAppResources), с помощью GWT.create(CellTableResources.class); в виджете, который нуждается в этом (или используя синглтон, как у меня для MyAppResources)?

MyAppResources:

public interface MyAppResources extends ClientBundle {
    public static final MyAppResources INSTANCE =  GWT.create(MyAppResources.class);

    @Source("MyAppStyles.css")
    public MyAppCssResource css();

    public CellTableResources cellTableResources();

}

CellTableResources:

public interface CellTableResources extends CellTable.Resources {

    interface CellTableStyle extends CellTable.Style {
    }

    @Override
    @Source({ CellTable.Style.DEFAULT_CSS, "CellTableStyles.css" })
    CellTableStyle cellTableStyle();

    @Source("green_light.png")
    ImageResource getGreenLight();

    //...
}

Спасибо за чтение.

1 ответ

Решение

Вопрос из нескольких частей, поэтому я попытаюсь ответить на этот вопрос в нескольких частях:

Какова стоимость GWT.create()?

Большинство из GWT класс - это "магия", то, что вы не можете написать для себя другими способами, так как они вызывают компилятор, чтобы заполнить для вас конкретные детали. Они часто отличаются при работе в режиме разработки и скомпилированы в JS.

В случае GWT.createполучается, что это скомпилировано в new - он используется только для создания новых экземпляров. Так какова стоимость нового экземпляра по сравнению с синглтоном? Это полностью зависит от создаваемого объекта. Если в объекте нет полей, тогда стоимость по существу бесплатна - фактически, компилятор может на самом деле удалить вызов конструктора и переписать все последующие методы как static тем не мение!

Это то, что происходит в большинстве случаев - GWT.create следует считать очень дешевым, если только вы не делаете глупости, например, вызываете это в цикле, который запускается много раз.

Что происходит, когда я перечисляю ClientBundle метод внутри другого ClientBundle?

Ну, что происходит, когда вы перечисляете что-нибудь внутри ClientBundle?

Все, что может быть указано в ClientBundle, должно быть отмечено @ResourceGeneratorType, указывая, как создать этот тип. Например, вот ImageResource:

/**
 * Provides access to image resources at runtime.
 */
@DefaultExtensions(value = {".png", ".jpg", ".gif", ".bmp"})
@ResourceGeneratorType(ImageResourceGenerator.class)
public interface ImageResource extends ResourcePrototype {
//...

Призывает ImageResourceGenerator создавать изображения по мере необходимости. Любой класс, описанный в этой аннотации, должен реализовывать com.google.gwt.resources.ext.ResourceGenerator, который описывает, как подготовиться к работе, как создать необходимые поля, как их инициализировать и как завершить.

Так как же это выглядит для самого ClientBundle? Проверять, выписываться com.google.gwt.resources.rg.BundleResourceGenerator - это очень простой класс, который просто вызывает GWT.create() по типу данного метода. Таким образом, предсказуемо, это означает, что эти "дочерние" ClientBundles создаются с помощью GWT.create, более или менее так же, как вы могли бы сделать в противном случае.

Хорошо, что это значит в данном конкретном случае?

Оказывается, что экземпляры ClientBundles не имеют полей, из которых они отслеживают вновь созданные объекты, но вместо этого имеют статические элементы, которые они используют вместо этого - эффективно одиночные. Это означает, что после того, как вы вызвали метод один раз, экземпляр, который он возвращает, будет таким же, как при следующем вызове. Разумеется, два разных ClientBundle с одинаковым содержимым будут сохранять две разные копии объектов, но не имеет значения, сколько раз вы создаете ClientBundle - его внутренние компоненты всегда будут одинаковыми.

Что-нибудь еще?

Ага! Помните, что здесь вы имеете дело с интерфейсами, а не с классами, поэтому вы можете расширять несколько раз за раз!

public interface MyAppResources extends 
       ClientBundle, 
       CellTable.Resources, 
       CellTree.Resources {//etc
  //...

Теперь, если два интерфейса описывают одни и те же методы, у вас могут возникнуть проблемы, но если нет, то это может обеспечить преимущество при генерировании изображений со ссылками. Каждый человек ClientBundle будет рисовать на своем собственном пуле изображений при подготовке их к использованию - если у вас есть ClientBundle в пределах ClientBundleони не будут работать вместе, чтобы спрайт изображения на большие куски. Чтобы получить это, вам нужно сделать только один ClientBundle тип. Это может не иметь значения в вашем конкретном случае, но я решил, что это также стоит упомянуть.

Другие вопросы по тегам