定期JavaFX服务

时间:2012-12-25 05:02:23

标签: java javafx-2

我想从JavaFX应用程序定期执行任务。该任务从远程流中提取数据。

虽然我知道我可以按照以下建议使用定时器:

JavaFX periodic background task

我相信这应该可以使用JavaFX Service对象来完成。在Javadoc中提到了指定一个自定义执行器(这里会想到ScheduledThreadPoolExecutor),但是如何指定周期和延迟呢?理想情况下,这将使用服务的常规启动,重置,重启和状态绑定......

public class MyFirstLineService extends Service<String> {
     private StringProperty url = new SimpleStringProperty(this, "url");
     public final void setUrl(String value) { url.set(value); }
     public final String getUrl() { return url.get(); }
     public final StringProperty urlProperty() { return url; }

     public MyFirstLineService() {
         setExecutor(new ScheduledThreadPoolExecutor());
     }

     protected Task createTask() {
         final String _url = getUrl();
         return new Task<String>() {
             protected String call() throws Exception {
                 URL u = new URL(_url);
                 BufferedReader in = new BufferedReader(
                         new InputStreamReader(u.openStream()));
                 String result = in.readLine();
                 in.close();
                 return result;
             }
         };
     }
 }

3 个答案:

答案 0 :(得分:3)

JavaFX issue tracker - RT18702

中请求了ScheduledService

跟踪器包含source for a preliminary implementation,但尚未纳入2.2分支。如果需要,您可以查看该来源,看看它是否有助于改进您的解决方案。

答案 1 :(得分:2)

我找到了一种方法来做到这一点,建立在上面sarcan的评论......

可以创建一个时间轴对象,通常用于动画UI元素,作为在FX应用程序线程上运行的计时器。使用它可以重新启动Service对象,然后Service对象在后台线程上执行长时间运行操作,同时通过FX Application Thread绑定保留属性访问和更新。

例如:

    final MyFirstLineService svc = new MyFirstLineService();
    final Duration oneFrameAmt = Duration.seconds(5);
    final KeyFrame oneFrame = new KeyFrame(oneFrameAmt,
            new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent evt) {
                    svc.restart();
                }
            });
    Timeline timer = TimelineBuilder.create()
                            .cycleCount(Animation.INDEFINITE)
                            .keyFrames(oneFrame)
                            .build();
    timer.playFromStart();

答案 2 :(得分:1)

遇到同样的问题。 ScheduledThreadPoolExecutor的示例可能是:

ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);

Service s = new Service(){
    @Override
    protected Task<String> createTask() {
        return new Task<String>() {
            @Override
            protected String call() throws Exception {
                // code...  
            }
        };
    }
}

// created tasks shall be run in thread pool
s.setExecutor(executor);

// start the service the first time
s.start();

// restart the service every 5 seconds
s.scheduleWithFixedDelay(new Runnable() {
        @Override
        public void run() {
            // need runLater here since trigger needs to be in the javaFX thread
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    checker.restart();
                }
            });
        }
    }, 0, 5, TimeUnit.SECONDS);
}

可以使用Timer解决但是您丢失了JavaFX数据绑定功能(如您所述)。期待Java8!