What is the cleanest way to obtain progress from a class that will also be used in a no-gui environment for the purpose of displaying said status in a JavaFX Gui?
Example:
import java.util.ArrayList;
import java.util.List;
public class ExampleFetcher {
public List<Entity> fetch() {
final List<Entity> results = new ArrayList<>();
for (int i = 0; i < N; i++) {
final Entity current = //Do some heavy work
results.add(current);
}
return results;
}
}
There are several possibilities, but to me each of them has some drawbacks
1. "The JavaFX way": Use an observable property from javafx.beans
import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.ReadOnlyDoubleWrapper;
import java.util.ArrayList;
import java.util.List;
public class ExampleFetcher {
private final ReadOnlyDoubleWrapper progress = new ReadOnlyDoubleWrapper();
public List<Entity> fetch() {
final List<Entity> results = new ArrayList<>();
for (int i = 0; i < N; i++) {
final Entity current = //Do some heavy work
progress.set((double) i / N);
results.add(current);
}
return results;
}
public double getProgress() {
return progress.get();
}
public ReadOnlyDoubleProperty progressProperty() {
return progress.getReadOnlyProperty();
}
}
Now you can simply observe the progressProperty or add a listener, which is quite nice, but it clutters the API a little. Also, is it even ok for a class to have a dependency on javafx
if it's not going to be used in some cases?
2. The naive way: Add consumers to the called method
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class ExampleFetcher {
public List<Entity> fetch(final Consumer<Double> progressConsumer) {
final List<Entity> results = new ArrayList<>();
for (int i = 0; i < N; i++) {
final Entity current = //Do some heavy work
progressConsumer.accept((double) i / N);
results.add(current);
}
return results;
}
}
You can pass a consumer that will update your progress bar or whatever you're using in the GUI. This avoids the dependency on javafx
but adds a lot of clutter to the API, especially if you're not only monitoring progress but some other kind of status.
Now, is there another way I'm not thinking about? Is one of the ways provided actually decent? Or should I maybe look into another way of executing my tasks?