Reputation: 95
So I am trying to have a method which will have a timer or a thread, so I can auto save every N minutes.(N is the number of minutes) I get N from my XML file, which can be changed anytime. So far this is what I have come up with
private void autoSave(){
Timer autoSaveTimer = new Timer();
autoSaveTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("Auto saving :D");
VB.save();
}
}, 0, autoSaveTime());
}
autoSaveTime(); just reads the number of minutes from the XMl file and converts it to milliseconds and returns the value. Currently if I change N, it doesn't change.
If there is a different approach I am welling to listen.
Upvotes: 0
Views: 343
Reputation: 209225
Consider using a scheduled service:
public class AutoSaveService implements ScheduledService<Void> {
@Override
protected Task<Void> createTask() {
// retrieve data from UI. This should be done here,
// as you should access the data on the FX Application Thread
final MyDataType data = getDataFromUI();
return new Task<Void>() {
@Override
protected Void call() throws Exception {
vb.save(data);
return null ;
}
};
}
}
You can use this as follows:
AutoSaveService autoSaveService = new AutoSaveService();
autoSaveService.setPeriod(Duration.seconds(5));
autoSaveService.start();
Calls to autoSaveService.setPeriod(...)
will be reflected in the time before subsequent tasks are created.
You can also do things like
autoSaveService.setOnFailed(e -> {
Throwable whatWentWrong = autoSaveService.getException();
// log exception, warn user, etc...
});
Here's a SSCCE (just prints a message instead of saving data):
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class AutoSaveExample extends Application {
@Override
public void start(Stage primaryStage) {
Spinner<Integer> saveIntervalSpinner = new Spinner<>(1, 60, 1);
AutoSaveService autoSaveService = new AutoSaveService();
autoSaveService.periodProperty().bind(Bindings.createObjectBinding(
() -> Duration.seconds(saveIntervalSpinner.getValue()),
saveIntervalSpinner.valueProperty()));
autoSaveService.start();
VBox root = new VBox(5, new Label("Save Interval:"), saveIntervalSpinner);
root.setAlignment(Pos.CENTER_LEFT);
root.setPadding(new Insets(18));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class AutoSaveService extends ScheduledService<Void> {
@Override
protected Task<Void> createTask() {
// retrieve data from UI. This should be done here,
// as you should access the data on the FX Application Thread
// final MyDataType data = getDataFromUI();
return new Task<Void>() {
@Override
protected Void call() throws Exception {
// vb.save(data);
System.out.println("Save at "+System.currentTimeMillis());
return null ;
}
};
}
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 2