In my Eclipse plugin, I have a TableViewer
that shows some data. These data is retrieved from a remote REST service. Therefore it takes some seconds to retrieve all items. That's why I wanted to add items to the TableViewer
's ContentProvider
as soon as I retrieve them. I do my REST query in a separate thread:
Thread retrieveThread = new RetrieveThread();
retrieveThread.run();
In this thread I add items to my TableViewer
:
MyView.instance.addItems(items);
And the same method in the class MyView
:
public void addItems(List<Result> items) {
ModelProvider.INSTANCE.addItems(items);
resultLabel.setText(ModelProvider.INSTANCE.getItems().size() + " items");
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
viewer.refresh();
}
});
}
I expected that this procedure will add items to my TableViewer
and then refresh the view. But what happens now is that my Eclipse freezes and adds all them items at the same time. How can I do this in a more responsive way?
The issue is that you are calling the run
method of your thread directly. This does not spawn a new thread, it just calls the run method in-line. retrieveThread.start()
would give you the behaviour you are looking for.
However, there is a better way of doing it (at least more 'eclipse friendly'), and that is to use an Eclipse Job
instead of a raw Thread
.
Job retrieveJob = new Job("Retrieving Data")
{
@Override
protected IStatus run(IProgressMonitor monitor) {
// do your REST call
ModelProvider.INSTANCE.addItems(items);
// if something goes wrong - don't return ok, obviously
return Status.OK_STATUS;
}
};
retrieveJob.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
if(event.getResult().isOK())
{
resultLabel.setText(ModelProvider.INSTANCE.getItems().size() + " items");
viewer.refresh();
}
}
});
// this will run in a background thread
// and nicely integrate with the UI
retrieveJob.schedule();