According to the SwingWorker
Javadoc:
When writing a multi-threaded application using Swing, there are two constraints to keep in mind:
- Time-consuming tasks should not be run on the Event Dispatch Thread. Otherwise the application becomes unresponsive.
- Swing components should be accessed on the Event Dispatch Thread only.
Thus, when using SwingWorker
, we must access Swing Components only in done()
and process()
methods.
So, I created a sample application which loads 3000 rows from database in chunks, each chunk with 50 rows and display it.
SwingWorker<List<Person>, Person> worker =
new SwingWorker<List<Person>, Person>() {
protected List<Person> doInBackground() {
List<Person> data = new ArrayList<>();
while (hasMoreData()) {
List<Person> chunk = loadFiftyRows();
data.addAll(chunk);
publish(chunk);
}
return data;
}
protected void process(List<Person> chunks) {
for (Person person : chunks) {
container.add(createPanelFor(person));
}
container.revalidate();
container.repaint();
}
};
worker.execute();
As, All swing access must be done on EDT, I am creating new JPanel
instances for each person
in the process()
method. But, still the application is quite heavy on start up. It freezes and response to the events while the data is loading, is quite late.
Although, we are publishing 50 rows at a time, the chunk size gets bigger when process()
method is invoked on EDT, sometimes 1000 rows. I think this is the cause of the delay, creating 1000 instances of JPanel
on EDT!
I feel, creating 1000 new instances of JPanel
is also a quite heavy task, to be performed on EDT. So, can't we create these JPanel
instances in doInBackground()
method, store it in a collection and then add those already created JPanel
instances to the container
in the process
method?
But, it will contradict the statement, "Swing components should be accessed on the Event Dispatch Thread only"!
Does this statement mean, Existing Swing Components that have been added to the Swing Component Hierarchy and not newly created Swing Components?