Обновление списка на javafx другим потоком - PullRequest
0 голосов
/ 06 ноября 2019

Мне нужно обновить просмотр списка на javafx, я попробовал два решения:

1.

Task task = new Task<Void>() {
    @Override public Void call() {
        while (true){
            visitsDataList = reqController.getVisits(userBean);
                Platform.runLater(() -> {
                    observableList.clear();
                    observableList.setAll(visitsDataList);
                    listVisits.setItems(observableList);
                    listVisits.setCellFactory(List -> new CustomVisitRow());
        });
        try {
                Thread.sleep(10000);
        } catch (InterruptedException e) {
                e.printStackTrace();
        }
    }
}
};

2.

new Thread(new Runnable() {
    @Override
    public void run() {
        while (true) {
            visitsDataList = reqController.getVisits(userBean);
            Platform.runLater(() -> {
                observableList.clear();
                observableList.setAll(visitsDataList);
                listVisits.setItems(observableList);
                listVisits.setCellFactory(List -> new CustomVisitRow());});
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();}}}}).start();

, но я не уверенпотому что я считаю, что создано слишком много Runnable. есть другие решения? какое из моих решений лучшее?

1 Ответ

2 голосов
/ 06 ноября 2019

Каждый цикл вы спите потоком в течение десяти секунд, что означает, что вы создаете Runnable и отправляете его на выполнение в Потоке приложения JavaFX один раз в десять секунд. Десять секунд - это вечность для компьютера. Другими словами, вы не создаете слишком много Runnable объектов и не перегружаете поток FX. Однако есть некоторые улучшения, которые можно сделать.

  1. Вам не нужно вызывать ObservableList#clear(), ListView#setItems или ListView#setCellFactory каждый цикл. Во-первых, установка фабрики ячеек должна происходить только один раз при первом создании и настройке ListView. И если предположить, что экземпляр observableList был установлен на ListView до запуска Thread, то достаточно вызвать #setAll. Этот метод эквивалентен вызову #clear, за которым следует #addAll.

    new Thread(() -> {
      while (true) {
        List<Visit> visits = reqController.getVisits(userBean);
        Platform.runLater(() -> observableList.setAll(visits));
        try {
          Thread.sleep(10_000L);
        } catch (InterruptedException ex) {
          break;
        }
      }
    }).start();
    
  2. Попробуйте вместо этого использовать javafx.concurrent.ScheduledService.

    // ScheduledService class
    public class VisitRefreshService extends ScheduledService<List<Visit>> {
    
      private final ObjectProperty<User> userBean = new SimpleObjectProperty<>(this, "userBean");
      private final ObjectProperty<Controller> reqController = new SimpleObjectProperty<>(this, "reqController");
    
      // getters, setters, and property getters omitted for brevity
    
      @Override
      protected Task<List<Visit>> createTask() {
        return new Task<>() {
    
          final User user = getUserBean();
          final Controller controller = getReqController();
    
          @Override
          protected List<Visit> call() throws Exception {
            return controller.getVisits(user);
          }   
        }
      }
    }
    
    // Using the ScheduledService
    VisitRefreshService service = new VisitRefreshService();
    service.setReqController(...);
    service.setUserBean(...);
    service.setExecutor(...); // Or don't set to use the default Executor
    service.setPeriod(Duration.seconds(10.0));
    service.setOnSucceeded(event -> observableList.setAll(service.getValue()));
    service.setOnFailed(event -> service.getException().printStackTrace());
    service.start();
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...