Skip to content

Commit

Permalink
Explicitly remove old dataprovider listener when new one is set (#12064
Browse files Browse the repository at this point in the history
…) (#12067)

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

If not done, this can cause memory leakage

Fixes: #12065
  • Loading branch information
Ansku authored Aug 10, 2020
1 parent 084ee81 commit 55ccf28
Showing 1 changed file with 35 additions and 7 deletions.
42 changes: 35 additions & 7 deletions server/src/main/java/com/vaadin/ui/ComboBox.java
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ public void resetForceDataSourceUpdate() {
// 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
* box can be set with {@link #setDataProvider(DataProvider)} or
Expand Down Expand Up @@ -885,6 +887,20 @@ public void attach() {

// Update icon for ConnectorResource
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
Expand Down Expand Up @@ -945,7 +961,10 @@ protected T readItem(Element child, Set<T> selected,

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

@Override
Expand All @@ -970,19 +989,28 @@ public <C> void setDataProvider(DataProvider<T, C> dataProvider,
filterSlot = filter -> providerFilterSlot
.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.
// Data sources for on the client need to be updated after data provider
// refreshAll so that serverside selection works even before the
// dropdown
// is opened. Only done for in-memory data providers for performance
// reasons.
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;
}
});
}
}

Expand Down

0 comments on commit 55ccf28

Please sign in to comment.