Слушатели источников данных (datasource listeners) позволяют получать оповещения об изменении состояния источников данных и экземпляров сущностей, в них находящихся.
Для регистрации слушателей используются методы Datasource.addListener()
, Datasource.removeListener()
. Пример регистрации слушателя в контроллере экрана:
@Inject private Datasource<Customer> customerDs; ... public void init(Map<String, Object> params) { ... customerDs.addListener(new DatasourceListener<Customer>() { // listener methods implementation }); }
Существует два интерфейса слушателей источников данных: DatasourceListener
и CollectionDatasourceListener
. Первый можно использовать для регистрации в любых источниках данных, второй - только в реализующих CollectionDatasource
. Как правило, на практике требуется получать не все оповещения от слушателя, а только некоторые. Поэтому удобно вместо реализации
самих интерфейсов слушателей использовать классы-адаптеры DsListenerAdapter
и CollectionDsListenerAdapter
, содержащие пустые реализации всех методов соответствующих интерфейсов.
Рассмотрим методы DatasourceListener
:
-
valueChanged()
- объявление этого метода наследуется от базового интерфейсаValueListener
. Данный метод слушателя вызывается, если изменилось значение какого-либо атрибута сущности, находящейся в данный момент в источнике. В метод передается сам измененный экземпляр, имя измененного атрибута, старое и новое значение.Оповещение
valueChanged()
можно использовать для действий в ответ на изменение пользователем сущности из UI, то есть редактирования полей ввода. В следующем примере гипотетический методupdateSettings()
будет вызван при изменении значения атрибутаactive
, и в него будет передано новое значение этого атрибута:@Inject private Datasource<Customer> customerDs; public void init(Map<String, Object> params) { ... customerDs.addListener(new DsListenerAdapter<Customer>() { @Override public void valueChanged(Customer source, String property, Object prevValue, Object value) { if ("active".equals(property)) { boolean active = BooleanUtils.isTrue((Boolean) value); // converting null to false updateSettings(active); } } }); }
-
itemChanged()
- вызывается при смене выбранного экземпляра, возвращаемого методомgetItem()
.Для
Datasource
это происходит при установке другого экземпляра (илиnull
) методомsetItem()
.Для
Пример использования оповещенияCollectionDatasource
данное оповещение вызывается, когда в связанном визуальном компоненте меняется выделенный элемент. Например, это может быть выделенная строка таблицы, элемент дерева, или выделенный элемент выпадающего списка.itemChanged()
для управления состоянием действия таблицы:@Inject protected CollectionDatasource<Customer, UUID> customersDs; @Named("customersTable.remove") protected RemoveAction removeAction; public void init(Map<String, Object> params) { ... customersDs.addListener(new DsListenerAdapter<Customer>() { @Override public void itemChanged(Datasource<Customer> ds, Customer prevItem, Customer item) { removeAction.setEnabled(canCustomerBeDeleted(item)); } }); }
-
stateChanged()
- вызывается при изменении состояния источника данных. Источник данных может находиться в одном из трех состояний, соответствующих перечислениюDatasource.State
:-
NOT_INITIALIZED
- источник только что создан. -
INVALID
- создан весьDsContext
, к которому относится данный источник. -
VALID
- источник данных в рабочем состоянии:Datasource
содержит экземпляр сущности илиnull
,CollectionDatasource
- коллекцию экземпляров или пустую коллекцию.
Получение оповещения об изменении состояния источника может быть актуально для сложных редакторов, состоящих из нескольких фреймов, где сложно отследить момент проставления редактируемой сущности в источник. В этом случае можно использовать оповещение
stateChanged()
для отложенной инициализации некоторых элементов экрана:@Inject protected CollectionPropertyDatasourceImpl<CategoryAttribute, UUID> categoryAttrsDs; categoryAttrsDs.addListener(new DsListenerAdapter<CategoryAttribute>() { @Override public void stateChanged(Datasource ds, Datasource.State prevState, Datasource.State state) { if (state != Datasource.State.VALID) return; initDataTypeColumn(); initDefaultValueColumn(); } });
-
Интерфейс CollectionDatasourceListener
добавляет еще один метод:
-
collectionChanged()
- вызывается при изменении коллекции сущностей, хранящейся в источнике данных. В метод передается тип изменения:REFRESH
,CLEAR
,ADD
,REMOVE
,UPDATE
.Пример слушателя, вызывающего пересчет стоимости поездки при изменении адреса остановки (сущность
Stop
) или количества остановок:protected class StopDsListener extends CollectionDsListenerAdapter<Stop> { @Override public void valueChanged(Stop source, String property, Object prevValue, Object value) { // existing stop address changed if ("address".equals(property)) { fireRouteChanged(); } } @Override public void collectionChanged(CollectionDatasource ds, Operation operation) { // stop was added or removed fireRouteChanged(); } private void fireRouteChanged() { // journey route has changed, need to recalculate price, journey time, pickup time delay etc. } }