Hi everyone!
I'm relatively new to GWT/GXT development. I'm trying to figure out why my application's memory consumption on the client side is increasing whenever I dynamically create panels.
I set up a minimal example to find out what's wrong:
Code:
public class EP implements EntryPoint {
PropPanel props;
@Override
public void onModuleLoad() {
RootPanel rp = RootPanel.get();
Viewport topPanel = new Viewport();
topPanel.setEnableScroll(false);
final BorderLayoutContainer panel = new BorderLayoutContainer();
topPanel.setWidget(panel);
TextButton b = new TextButton("Reload");
final Viewport scroll = new Viewport();
scroll.setEnableScroll(true);
b.addSelectHandler(new SelectHandler() {
@Override
public void onSelect(SelectEvent event) {
if (props!=null) {
scroll.remove(props);
}
props = new PropPanel();
scroll.setWidget(props);
}
});
panel.setNorthWidget(b);
panel.setCenterWidget(scroll);
rp.add(topPanel);
}
}
public class PropPanel implements IsWidget{
static int counter = 0;
private FlowLayoutContainer panel;
public PropPanel() {
panel = new FlowLayoutContainer();
for (int i=0; i<1000; i++) {
TextButton b = new TextButton("TestButton "+counter);
b.addSelectHandler(new SelectHandler() {
@Override
public void onSelect(SelectEvent event) {
MessageBox mb = new MessageBox("Hallo");
mb.show();
}
});
panel.add(b);
}
counter++;
}
@Override
public Widget asWidget() {
return panel;
}
}
This app has a button labeled "Reload" and a widget "PropPanel" which is a FlowLayoutContainer that contains 1000 buttons. Now when the user hits the "Reload" button, the PropPanel removed and replaced by a new one created from scratch.
I used Chrome's developer tools to examine what happens when the new PropPanel is replaced. It seems that there are still references to the old panel dangling around somewhere, as there are way more objects created than deleted:
memleaktest-gxt.jpg
I've recreated the same example using plain GWT only, to see if it is a general GWT problem:
Code:
public class EP implements EntryPoint {
PropPanel props;
@Override
public void onModuleLoad() {
RootPanel rp = RootPanel.get();
final DockPanel panel = new DockPanel();
Button b = new Button("Reload");
final ScrollPanel scroll = new ScrollPanel();
b.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (props!=null) {
scroll.remove(props);
}
props = new PropPanel();
scroll.setWidget(props);
}
});
panel.add(b, DockPanel.NORTH);
panel.add(scroll, DockPanel.SOUTH);
rp.add(panel);
}
}
public class PropPanel implements IsWidget {
static int counter = 0;
private FlowPanel panel;
public PropPanel() {
panel = new FlowPanel();
for (int i=0; i<1000; i++) {
Button b = new Button("TestButton "+counter);
b.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Window.alert("Hallo");
}
});
panel.add(b);
}
counter++;
}
@Override
public Widget asWidget() {
return panel;
}
}
However, when running the plain GWT example, everything seems to be collected fine:
memleaktest-gwt.jpg
All the tests were done using compiled code (not hosted mode).
Did I forget something in my GXT code or is this general problem with GXT widgets that are created on the fly? I hope someone of you guys can help me.
Thanks in advance!
Tom