Слушатели источников данных (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. } }

