问题描述
我有一个 SwingWorker
类,它的 doInBackground
在远程数据库上执行查询。我调用 publish(true)
将 setVisible
设置为 true 以使 jdialog 保持加载器动画。
一切正常:
但是,当我将应用程序指向在本地计算机上运行的数据库时,会显示 jdialog,但从未关闭/处置,即使调用了 done()
。这也会停止执行 done 方法中的 UI 代码,直到我手动关闭加载器对话框。
这种奇怪的行为如下:
我必须提到,在远程数据库上执行需要 10 秒或更长时间,但在我的本地数据库上只需要一秒钟。更快的速度如何导致这种奇怪的行为?
以下是我的代码片段:
@H_502_54@ new SwingWorker<Void,Boolean>() {
jdialog loader = new MyDialogLoader();
@Override
protected Void doInBackground() {
publish(true);
//DATABASE EXECUTION CODE IS HERE
publish(false);
return null;
}
@Override
protected void process(List<Boolean> chunks) {
for (Boolean val : chunks) {
loader.setVisible(val);
}
}
@Override
protected void done() {
loader.dispose();
//UI UPDATE WITH DATABASE VALUES CODE HERE;
}
}.execute();
解决方法
可能是在 doBackground()
中抛出了一个异常,所以 publish(false)
没有被执行。可能是访问数据库出错...
doBackground
抛出的异常被 SwingWorker
静默捕获并保存。检查是否抛出此类异常的方法是调用 get()
方法中的 done()
方法。它将抛出一个 ExecutionException
,原始异常为 cause
:
@Override
protected void done() {
loader.dispose();
try {
get();
} catch (ExecutionException ex) {
ex.printStackTrace();
// some message or what ever using ex.getCause()
} catch (InterruptedException ex) {
ex.printStackTrace();
// TODO
}
//UI UPDATE WITH DATABASE VALUES CODE HERE;
}
,
我分享这个作为答案,因为它已经解决了这个问题。
我取消了 publish
和 process
方法;加载器 JDialog 现在从 doInBackground
可见。为确保在事件调度线程上执行此 UI 交互,该语句放置在 SwingUtilities.invokeLater
中。
new SwingWorker<Void,Void>() {
JDialog loader = new MyDialogLoader();
@Override
protected Void doInBackground() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
loader.setVisible(true);
} catch (Exception e) {
e.printStackTrace()
}
}
});
//DATABASE EXECUTION CODE IS HERE
return null;
}
@Override
protected void done() {
loader.dispose();
//UI UPDATE WITH DATABASE VALUES CODE HERE;
}
}.execute();