这是一个简单的类,它使用冒泡排序对List
Integer
进行排序,并将每次迭代的结果从RxJava库推送到Subject
,但有一些延迟。
public class Sorter {
private PublishSubject<List<Integer>> subject = PublishSubject.create();
public void bubbleSort(int delay) throws InterruptedException {
List<Integer> ints = randomIntegers(0,200,10);
for (int i = 0; i < ints.size(); i++) {
for (int j = 0; j < ints.size() - 1; j++) {
if (ints.get(j) > ints.get(j + 1)) {
Collections.swap(ints, j, j + 1);
subject.onNext(ints);
Thread.sleep(delay);
}
}
}
}
private List<Integer> randomIntegers(int origin, int bound, int limit) {
return new Random()
.ints(origin, bound)
.limit(limit)
.boxed()
.collect(Collectors.toList());
}
public PublishSubject<List<Integer>> getSubject() {
return subject;
}
}
我可以使用示例代码轻松地观察结果:
int delay = 100;
Sorter sorter = new Sorter();
PublishSubject<List<Integer>> subject = sorter.getSubject();
subject.subscribe(System.out::println);
sorter.bubbleSort(delay);
但是,我希望将迭代的结果看作移动代表数字的不同高度的矩形。我使用JavaFX。每次迭代后,我想清除应用程序窗口并重绘所有内容。
public class Main extends Application {
private Group root;
@Override
public void start(Stage primaryStage) throws InterruptedException {
root = new Group();
Scene scene = new Scene(root, 500, 500, Color.WHITE);
primaryStage.show();
primaryStage.setScene(scene);
Sorter sorter = new Sorter();
PublishSubject<List<Integer>> subject = sorter.getSubject();
subject.subscribe(this::drawRectangles);
sorter.bubbleSort(100);
}
private void drawRectangles(List<Integer> integers) {
root.getChildren().clear();
rectangles.clear();
for (int i = 0; i<integers.size(); i++) {
Rectangle rectangle = new Rectangle(i * 20, 500 - integers.get(i), 10, integers.get(i));
rectangle.setFill(Color.BLACK);
rectangles.add(rectangle);
}
root.getChildren().addAll(rectangles);
}
public static void main(String[] args) {
launch(args);
}
}
但是,我只看到最后一次迭代的结果。在此之前,我只能看到应用程序正在运行并且GUI线程被阻止。
如何让后台RxJava计算无阻塞到我的GUI?
编辑:我通过在另一个线程中运行计算代码解决了这个问题,如下所示:
@Override
public void start(Stage primaryStage) throws InterruptedException {
new Thread(() -> {
Sorter sorter = new Sorter();
sorter.getSubject().subscribe(this::drawRectangles);
try {
sorter.bubbleSort(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
root = new Group();
Scene scene = new Scene(root, 1500, 500, Color.WHITE);
primaryStage.show();
primaryStage.setScene(scene);
}
将drawRectangles
包装在Platform.runLater(() -> {}
表达式中。
这似乎有效,虽然我觉得我可能会以observeOn
以某种方式运行它。
答案 0 :(得分:0)
使用RxJavaFX
调度您的UI任务。
您需要在另一个线程而不是UI线程中执行排序任务sorter.bubbleSort
。和
observeOn(JavaFxScheduler.getInstance())
将UI任务安排回UI线程。
仅将start
方法更改为:
@Override
public void start(Stage primaryStage) throws InterruptedException {
root = new Group();
Scene scene = new Scene(root, 500, 500, Color.WHITE);
primaryStage.show();
primaryStage.setScene(scene);
Sorter sorter = new Sorter();
sorter.getSubject()
.observeOn(JavaFxScheduler.platform())
.subscribe(this::drawRectangles);
new Thread(() -> uncheck(() -> sorter.bubbleSort(100))).start();
}