这是一个更普遍的问题。我们有很多向导,其中一些启动了一个长时间运行的过程并显示结果。问题是:进行长时间计算的正确方法是什么?
以前大多数巫师都在DialogPage#setVisible
做了他们的计算,就像那样:
public void setVisible(final boolean visible) {
if (visible) {
getWizard().getContainer().run(true, true, new MyCalculation());
}
super.setVisible(visible);
}
我认为这不是一个好主意,因为通常getWizard()
会在这些方法中被调用很多。此外,通常将父向导强制转换为特定实现以从中获取输入值或将结果设置为其他页面。所以通常它看起来像这样:
public void setVisible(final boolean visible) {
if (visible) {
Input input = ((MyCalculationWizard)getWizard()).getInputPage().getInput();
MyCalculation calculation = new MyCalculation(input);
getWizard().getContainer().run(true, true, calculation);
Output output = calculation.getOutput();
((MyCalculationWizard)getWizard()).getOtherPage().setOutput(output);
}
super.setVisible(visible);
}
只是看看你知道的代码非常糟糕的代码。
所以我们用在Wizard#getNextPage()
中计算的内容替换它:
public IWizardPage getNextPage(final IWizardPage page) {
final IWizardPage nextPage = super.getNextPage(page);
if (nextPage == this.myResultPage)
getContainer().run(true, true, new MyCalculation());
return nextPage;
}
这样,向导能够比页面更好地微调,并且向导已经知道它的页面并且可以比页面更好地处理输入和输出。
缺点是:getNextPage()
会因为更新按钮而被调用很多,每次真正的向导都会感觉像这样。因此,虽然它适用于小型流程,但它并不适用于长期运行的流程。
经过一些更多的讨论后,我发现以下内容可以在覆盖Wizard#setContainer
时发挥作用:
public void setContainer(final IWizardContainer wizardContainer) {
final IWizardContainer oldContainer = getContainer();
if (oldContainer instanceof WizardDialog)
((WizardDialog) oldContainer).removePageChangingListener(this);
super.setContainer(wizardContainer);
if (wizardContainer instanceof WizardDialog)
((WizardDialog) wizardContainer).addPageChangingListener(this);
}
public void handlePageChanging(final PageChangingEvent event) {
final IWizardPage currentPage = (IWizardPage) event.getCurrentPage();
final IWizardPage nextPage = (IWizardPage) event.getTargetPage();
if (currentPage == this.myInputPage && nextPage == this.myResultPage)
getContainer().run(true, true, new MyCalculation());
}
这里的一大优点是,如果向导想要在页面之间跳转,则只会调用侦听器,并且我们能够真正微调计算(例如,在调用'Previous'时不调用)。我们甚至无法显示下一页(event.doit = false
)。
缺点是将容器转换为WizardDialog
,因为它可能是完全不同的实现。
所以问题是:在向导中启动长进程的最佳方法是什么?