Browse Source

Explicitly remove old dataprovider listener when new one is set (#12064)

* Explicitly remove old dataprovider listener when new one is set

If not done, this can cause memory leakage

* Formatting

* Fixed coding style

* Take into account further scenarios

Component maybe detached permanently and thus data provider listener needs to be remove in detach. Also if this is only momentary remove from layout add back cycle, re-setup is needed in attach, in case it was not already setup before attaching by setDataProvider.

* Change super.detach() call order

* Added null check to getDataProvider

* Setting dataProviderListener to null on detach

* Removing listener only if it exists

* Fix
tags/8.12.0.alpha1
Tatu Lund 3 years ago
parent
commit
415acb75f7
No account linked to committer's email address
1 changed files with 35 additions and 7 deletions
  1. 35
    7
      server/src/main/java/com/vaadin/ui/ComboBox.java

+ 35
- 7
server/src/main/java/com/vaadin/ui/ComboBox.java View File

// Just ignore when neither setDataProvider nor setItems has been called // Just ignore when neither setDataProvider nor setItems has been called
}; };


private Registration dataProviderListener = null;

/** /**
* Constructs an empty combo box without a caption. The content of the combo * Constructs an empty combo box without a caption. The content of the combo
* box can be set with {@link #setDataProvider(DataProvider)} or * box can be set with {@link #setDataProvider(DataProvider)} or


// Update icon for ConnectorResource // Update icon for ConnectorResource
updateSelectedItemIcon(getValue()); updateSelectedItemIcon(getValue());

DataProvider<T, ?> dataProvider = getDataProvider();
if (dataProvider != null && dataProviderListener == null) {
setupDataProviderListener(dataProvider);
}
}

@Override
public void detach() {
if (dataProviderListener != null) {
dataProviderListener.remove();
dataProviderListener = null;
}
super.detach();
} }


@Override @Override


@Override @Override
public DataProvider<T, ?> getDataProvider() { public DataProvider<T, ?> getDataProvider() {
return internalGetDataProvider();
if (this.getDataCommunicator() != null) {
return internalGetDataProvider();
}
return null;
} }


@Override @Override
filterSlot = filter -> providerFilterSlot filterSlot = filter -> providerFilterSlot
.accept(convertOrNull.apply(filter)); .accept(convertOrNull.apply(filter));


setupDataProviderListener(dataProvider);
}

private <C> void setupDataProviderListener(
DataProvider<T, C> dataProvider) {
// This workaround is done to fix issue #11642 for unpaged comboboxes. // This workaround is done to fix issue #11642 for unpaged comboboxes.
// Data sources for on the client need to be updated after data provider // Data sources for on the client need to be updated after data provider
// refreshAll so that serverside selection works even before the // refreshAll so that serverside selection works even before the
// is opened. Only done for in-memory data providers for performance // is opened. Only done for in-memory data providers for performance
// reasons. // reasons.
if (dataProvider instanceof InMemoryDataProvider) { if (dataProvider instanceof InMemoryDataProvider) {
dataProvider.addDataProviderListener(event -> {
if ((!(event instanceof DataChangeEvent.DataRefreshEvent))
&& (getPageLength() == 0)) {
getState().forceDataSourceUpdate = true;
}
});
if (dataProviderListener != null) {
dataProviderListener.remove();
}
dataProviderListener = dataProvider
.addDataProviderListener(event -> {
if ((!(event instanceof DataChangeEvent.DataRefreshEvent))
&& (getPageLength() == 0)) {
getState().forceDataSourceUpdate = true;
}
});
} }
} }



Loading…
Cancel
Save