Eclipse E4 RCP条件阻止视图导航及栈溢出问题求解
解决Eclipse E4中因强制视图切换导致的StackOverflowError问题
这个问题的核心是无限递归调用:当你在partDeactivated方法中检测到数据变更时,直接调用showPerspective和showPart强制切回目标视图,而激活这些视图的操作又会触发其他部件的partDeactivated事件,进而再次触发你的强制导航逻辑,循环往复直到栈溢出。
下面是具体的解决方案:
1. 添加递归防护标志
首先在包含partDeactivated方法的类中添加一个布尔变量,用来标记当前是否正在执行强制导航操作,避免重复进入逻辑:
// 类级别的递归防护标志,初始为false private boolean isForcingNavigation = false;
2. 修改partDeactivated方法,加入防护逻辑
在触发强制导航前先检查标志,如果已经在导航流程中就直接跳过;执行导航时锁定标志,执行完成后再重置,确保不会递归触发:
public void partDeactivated(@Active MPart part) { if (partInstance.getElementId() != part.getElementId()) { return; } // 保留原有事务处理逻辑 if (transactionButton != null && !transactionButton.isDisposed() && transactionButton.isEnabled() && isTransactionCompleted && NavigationHelper.getEditableViewInstance() != null && !partDeactivateFlag) { doTransaction(); partDeactivateFlag = true; } if (Navigation.isPerspective()) { if (EModel.getInstance().hasDataChanged()) { // 核心:避免递归进入强制导航逻辑 if (isForcingNavigation) { return; } isForcingNavigation = true; try { System.out.println("Changes"); NavigationHelper.showPerspective(CommonConstants.PERSPECTIVE1, getEclipseContext()); NavigationHelper.showPart(CommonConstants.VIEW1, getEclipseContext()); NavigationHelper.showPart(CommonConstants.VIEW2, getEclipseContext()); } finally { // 无论执行结果如何,都重置标志 isForcingNavigation = false; } } } viewDeactivated(); }
3. 优化findPartAndActivate方法,减少不必要的激活操作
在激活部件前先检查它是否已经处于激活状态,如果已经激活就跳过activate调用,这样可以减少不必要的partDeactivated事件触发:
private static boolean findPartAndActivate(String partId, IEclipseContext eclipseContext, boolean giveFocus) { MTrimmedWindow applicationWindow = ((MTrimmedWindow) ((MApplication) eclipseContext.get(MApplication.class)) .getChildren().get(0)); IEclipseContext currentContext = applicationWindow.getContext(); EPartService partService = currentContext.get(EPartService.class); EModelService modelService = currentContext.get(EModelService.class); MPart part = (MPart) modelService.find(partId, eclipseContext.get(MApplication.class).getChildren().get(0)); // 仅当部件未激活时才执行激活操作 if (part != null && !part.isActive()) { partService.activate(part, giveFocus); } return true; }
为什么这样有效?
- 递归防护标志
isForcingNavigation在进入强制导航流程时被设为true,此时如果其他部件的partDeactivated事件触发,会直接跳过强制导航逻辑,打破无限循环。 - 激活前检查部件状态的优化,避免了对已激活部件的重复操作,减少了事件触发次数,同时提升了性能。
内容的提问来源于stack exchange,提问作者VC_Vish
相关产品推荐
相关产品推荐

