在插件启动期间执行UI相关操作的正确方法是什么

时间:2016-04-11 12:43:02

标签: eclipse-plugin eclipse-rcp

我需要执行UI操作,例如“删除eclipse默认菜单”,“注册IWindowCloseHandler”和“添加IWorkbenchListener”等。

所有上述操作都在插件start()方法

中完成
start(BundleContext context) {
 ....

Display.getDefault().syncExec(new Runnable() {
 @Override
 public void run() {
    //Disable/Remove eclipse default menu items like Edit, Run etc

    //register workbence register
    final IWorkbench workbench = PlatformUI.getWorkbench();
    final IWorkbenchPage activePage =    workbench.getActiveWorkbenchWindow().getActivePage();
    workbench.getActiveWorkbenchWindow().addPerspectiveListener(pHandler);
    workbench.addWorkbenchListener(new IWorkbenchListener(){                    
        @Override
        public boolean preShutdown(IWorkbench workbench, boolean forced) {
        activePage.closeEditors(activePage.getEditorReferences(), true);
                            return true;
        }
    });     
     //register close handler
     ExitHandler.registerExitHandler();
    }
 }); 
}

public class ExitHandler {
  public static void registerExitHandler() {
     WorkbenchWindow activeWorkbenchWindow = (WorkbenchWindow) PlatformUI.getWorkbench().getActiveWorkbenchWindow();
    if (activeWorkbenchWindow != null) {
        MWindow window = activeWorkbenchWindow.getModel();
        if (window != null) {
            window.getContext().set(IWindowCloseHandler.class, new IWindowCloseHandler() {

                @Override
                public boolean close(MWindow window) {
                    //Exit logic involves UI;
                }
            });
        }
    }
  }
} 

有时我在Display.asyncExec()/ syncExec()中引用的许多类的异常低于:

 !MESSAGE While loading class "ExitHandler ", thread "Thread[main,6,main]" timed out waiting (5011ms) for thread "Thread[Thread-6,5,main]" to finish starting bundle "bundlename". To avoid deadlock, thread "Thread[main,6,main]" is proceeding but "ExitHandler " may not be fully initialized.

执行这些操作的正确位置是什么?

  1. 在org.eclipse.ui.IStartup或
  2. 的earlyStartUp()中
  3. 在org.osgi.framework.BundleListener的bundleChanged()中或在生命周期类中。
  4. 我怀疑上面两个选项!!还有其他合适的选择吗?
  5. 观察:当我的品牌插件发生变化时,会发现上述问题,否则加载工作正常

3 个答案:

答案 0 :(得分:0)

使用IStartup方法,但您需要使用Display.asyncExec来延迟代码的运行,直到工作台启动完成为止:

public void earlyStartup()
{
  Display.getDefault().asyncExec(new Runnable() {
    @Override
    public void run() {
      // TODO your code here
    }
  });
}

答案 1 :(得分:0)

避免这种情况的一种方法是将所有代码放在激活码的最后,以便在不加载其他类的情况下快速退出。

最好使用aysnc执行,因为bundle激活线程将立即返回并将进入活动状态,否则捆绑激活线程将被阻止,直到您的服务结束。

Start(BundleContext context) {
 ....
// this is my last call in the start() method
Display.getDefault().syncExec(new Runnable() {
 @Override
 public void run() {
    //UI logic to disable 
    }
  }
} 

答案 2 :(得分:0)

我按照以下方法解决了上述问题:

  1. 菜单启用/禁用已在我的视图的init()中完成,该视图在我的包启动后加载。
  2. 注册听众,例如IWindowCloseHandler'和' IWorkbenchListener'在捆绑启动后,我的' BundleListener'中正在完成。

    public class StudioBundleListener implements BundleListener {
     @Override
       public void bundleChanged(BundleEvent event) {
       String symbolicName = event.getBundle().getSymbolicName();
       int type = event.getType();
       if(symbolicName.equals(MYPlugin.PLUGIN_ID) && type == BundleEvent.STARTED) {
         //Register your listeners
       }
      }
    }
    
  3. 捆绑激活码最后的IStartup和async()仍然会导致类加载问题,如问题部分所述。