问题描述
因此,我有一个非常非常简单的应用程序,应该可以处理下载某些文件并将它们更新到某个目录的情况。 该应用程序具有一个带状态栏的简单界面,该栏应告诉用户下载过程的进展情况。 到现在为止还挺好。
我有一些扩展javafx.concurrent.Task类的类的实现。 这些类负责处理每个系统的文件下载和保存,并注意每个系统的特殊性。 每个人的下载过程本身(实际上来自远程数据库)是相同的,因此,它在另一个称为FileDownloader的类中实现,因为它自然是可以重用的。
因此,我们有一个带有Task ()方法的UpdateTask类,该方法又调用FileDownloader类中的某些方法。
麻烦是:我需要将progressProperty绑定到栏中,但是只有UpdateTask才具有此属性,而我想在栏中显示的大部分工作都在FileDownloader中完成。 我无法从download方法中调用updateProgress,因为它不在Task类中。 我无法将任务传递给方法并在那里调用update方法。 我无法在progress属性上创建侦听器,也无法侦听downloader类内部字段的更改。 看来我什么也做不了,唯一的解决办法是计算出call()方法内正在完成的工作。 麻烦是我。
有没有解决这个问题的方法,而无需我编写更少可重用的代码? 示例代码如下:
public class UpdateTask extends Task<Void> {
@Override
protected Void call() throws Exception {
//some other operations are performed before this part
FileDownloader downloader = new FileDownloader();
//The stuff I wanna count is in there :(
boolean isDownloaded = downloader.downloadSysVersion();
//some other stuff happens that depends on the completion of the download
}
谁向我展示了如何从downloadSysVersion方法内部获取信息,则将获得免费的Internet cookie。
1楼
在FileDownloader
类中添加代表进度的属性。
例如,如果要公开下载的字节数,则可以执行
public class FileDownloader {
private final ReadOnlyLongWrapper bytesDownloaded = new ReadOnlyLongWrapper();
public final long getBytesDownloaded() {
return bytesDownloaded.get();
}
public final ReadOnlyLongProperty bytesDownloadedProperty() {
return bytesDownloaded.getReadOnlyProperty();
}
private long totalBytes ;
public long getTotalBytes() {
return totalBytes ;
}
// other code as before...
public boolean downloadSysVersion() {
// code as before, but periodically call
bytesDownloaded.set(...);
// ...
}
}
你现在做
@Override
protected Void call() throws Exception {
FileDownloader downloader = new FileDownloader();
downloader.bytesDownloadedProperty().addListener((obs, oldValue, newValue) ->
updateProgress(newValue.longValue(), downloader.getTotalBytes()));
boolean isDownloaded = downloader.downloadSysVersion();
// ...
}
如果要使FileDownloader
类独立于整个JavaFX API(包括属性类),则可以改用LongConsumer
:
public class FileDownloader {
private LongConsumer progressUpdate ;
public void setProgressUpdate(LongConsumer progressUpdate) {
this.progressUpdate = progressUpdate ;
}
private long totalBytes ;
public long getTotalBytes() {
return totalBytes ;
}
public boolean downloadSysVersion() {
// periodically do
if (progressUpdate != null) {
progressUpdate.accept(...); // pass in number of bytes downloaded
}
// ...
}
}
在这种情况下,您的任务看起来像
@Override
protected Void call() throws Exception {
FileDownloader downloader = new FileDownloader();
downloader.setProgressUpdate(bytesDownloaded ->
updateProgress(bytesDownloaded, downloader.getTotalBytes()));
boolean isDownloaded = downloader.downloadSysVersion();
// ...
}
无论使用哪种设置,您都可以照常将进度条的progressProperty
绑定到任务的progressProperty
。
2楼
在您的UpdateTask类中,添加:
@Override
public void updateProgress(double workDone, double max) {
super.updateProgress(workDone, max);
}
您需要以某种方式(可能是通过构造函数)将UpdateTask实例传递给FileDownlader实例实例。 然后,您应该可以调用updateProgress。