Gracefully Loading a Heavy Plugin
Here's the challenge: I have a plug-in which may take more than a few seconds to load. That's not a problem if the plug-in is loaded when the platform starts since the user waits for platform to load anyway. However, if the plug-in is loaded on-demand, after the platform is already started, the user may experience an unexplained freeze.
To overcome this behavior, it is best to use some progress dialog with a monitor when starting your plugin. This is simple, however, the less-than-trivial question is: how to determine if the platform is starting?
Those with some knowledge of Eclipse would simply direct me to a very simple API call:
PlatformUI.isWorkbenchRunning()
One major disadvantage.. this is useless, since it will return true when the platform is still loading as well. It is considered running at this point.
Searching in the Eclipse newsgroups portal, I came across another idea
:
Bundle b = Platform.getBundle("org.eclipse.swt");
if (b==null || b.getState() != Bundle.ACTIVE) {
System.out.println("no UI...");
}
This doesn't work, since SWT is already resolved when the splash screen is shown. You can test other bundles, if you'd like, but I find it hard to believe you'll discover any well-defined and consistent difference between the two situations: loading upon launch and loading after it is complete.
My next idea was to check the visibility of the default shell. Nope, it is considered visible at startup. I tried checking for the existence of workbench visual parts and, guess what, they're already there in both cases. After some trial and error I found a very simple way of doing that. One of the distinct features when the splash screen is showing is that you don't see a menu-bar. From that I derived the following test:
Display.getCurrent().getActiveShell().getMenuBar() == null
This will return true when the platform is still launching and a splash screen is shown. Putting it all together and adding all the null checks I could think of, I wrote the following method for checking if the shell is already open and return it if it is:
private Shell findStartedShell() {
Shell result = null;
final Display currentDisplay = Display.getCurrent();
if (currentDisplay != null) {
result = currentDisplay.getActiveShell();
if ((result != null) && (result.getMenuBar() == null)) {
result = null;
}
}
return result;
}I used a ProgressMonitorDialog to show the progress and an IRunnableWithProgress to implement the lengthy startup process. Eventually, the plugin Activator start method would look like this:
public void start(final BundleContext context) throws Exception {
super.start(context);
plugin = this;
final IRunnableWithProgress statupOperation =
new IRunnableWithProgress() {
public void run(final IProgressMonitor monitor) throws
InvocationTargetException, InterruptedException {
// do your initialization here
// use the monitor to set the task name
// and report progress
}
};
final Shell activeShell = findStartedShell();
if (activeShell != null) {
final ProgressMonitorDialog progressMonitorDialog =
new ProgressMonitorDialog(activeShell);
progressMonitorDialog.run(false, false, statupOperation);
} else {
statupOperation.run(new NullProgressMonitor());
}
}
The above will do exactly what we were looking for: if the platform is launching, it will proceed with normal startup (the splash screen shows the progress of loading all the plugins) and, if the platform is already loaded, it will show a progress dialog.
Found a better way of doing that? Let me know in the comments.
From http://zvikico.typepad.com
- Login or register to post comments
- 1642 reads
- Email this Article
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)







Comments
jeervin92 replied on Wed, 2008/07/23 - 1:32pm
jeervin92 replied on Wed, 2008/07/23 - 1:47pm
jeervin92 replied on Wed, 2008/07/23 - 1:55pm
jeervin92 replied on Wed, 2008/07/23 - 2:26pm
jeervin92 replied on Wed, 2008/07/23 - 2:27pm
Min Idzelis replied on Thu, 2008/07/24 - 8:53pm
Zviki Cohen replied on Fri, 2008/07/25 - 12:01am
@Min,
You are correct, I tried that technique first. Here's the problem - my plugin becomes active when the user opens a view. The view needs the plugin to be fully loaded. Hence, I cannot allow this to happen in parallel, not knowing who will finish first.
I could modify the view to check if everything is loaded and if not show a message until it is. But that's not only one view, it's several views, so It's quite a bit of work.