0

I am constantly pulling data (about 10-15 items) from my database (every 2 seconds) everytime it updates the ui just freezes.

I've tried using scheduledservice, thread and tasks in order to update the UI but it always freezes.

I've also tried using observable list for the tableview and just removeAll() and addAll() (according to JavaFX 2.1 TableView refresh items)

Is there a way to avoid blocking the ui thread?

EDITED:

It doesn't lag if I remove the tableViewConcern.getItems().setAll(service.getValue()); part but as soon as I start adding stuff into the database it becomes slower and slower (until it stops).

Inside my ActiveConcernService (ScheduledService) it just gets data from the database.

public class ActiveConcernService extends ScheduledService<ObservableList<Concern>> {
    private UserAccount currentUser;
    public ActiveConcernService(UserAccount currentUser) {
        this.currentUser = currentUser;
    }

public final ObservableList<Concern> getConcerns() {
    ObservableList<Concern> concerns;
    if(RoleService.getInstance().getById(currentUser.getRoleId()).getTitle().equals(Role.DefaultRole.ADMIN.getRole())){
        concerns = FXCollections.observableList(ConcernService.getInstance().allNotDone());         
    } else {
        concerns = FXCollections.observableList(ConcernService.getInstance().allByUser(currentUser));           
    }
    return concerns; //gets the data from database base on the user role
}

@Override
protected Task<ObservableList<Concern>> createTask() {
    return new Task<ObservableList<Concern>>() {
        @Override
        protected ObservableList<Concern> call() {
            return getConcerns();
        }
    };
}

And in my Controller this is how I initialize my table column header and the scheduledservice does are the only two part where the table is being used.

@Override
public void initialize(URL arg0, ResourceBundle arg1) {
    // Initializes other ui elements (textfield, button, choicebox, etc)
    initializeConcernTable();
    ActiveConcernService service = new ActiveConcernService(currentUser);
    service.setPeriod(Duration.millis(2000));
    service.setOnSucceeded((t) -> {
        tableViewConcern.getItems().setAll(service.getValue()); //Everytime this executes it lags
    });
    service.start();
}

private void initializeConcernTable() {

    TableColumn<Concern, String> clientColumn = new TableColumn<>(Concern.NAME_HEADER);
    clientColumn.setCellValueFactory(param -> param.getValue().getClientNameProperty());
    clientColumn.setMinWidth(125);
    clientColumn.setSortable(false);

    TableColumn<Concern, String> remarkColumn = new TableColumn<>(Concern.REMARK_HEADER);
    remarkColumn.setCellValueFactory(param -> param.getValue().getRemarkProperty());
    remarkColumn.setMinWidth(175);
    remarkColumn.setSortable(false);

    TableColumn<Concern, String> categoryColumn = new TableColumn<>(Concern.CATEGORY_HEADER);
    categoryColumn.setCellValueFactory(param -> new SimpleStringProperty(
            CategoryService.getInstance().getById(param.getValue().getCatergoryId()).getTitle()));
    categoryColumn.setMinWidth(150);
    categoryColumn.setSortable(false);

    TableColumn<Concern, String> assignToColumn = new TableColumn<>(Concern.EMPLOYEE_HEADER);
    assignToColumn.setCellValueFactory(param -> new SimpleStringProperty(
            UserAccountService.getInstance().getById(param.getValue().getUserAccountId()).getName()));
    assignToColumn.setMinWidth(125);
    assignToColumn.setSortable(false);

    TableColumn<Concern, String> numberColumn = new TableColumn<>(Concern.NUMBER_HEADER);
    numberColumn.setCellValueFactory(param -> new ReadOnlyObjectWrapper<String>(param.getValue().getNumber() + ""));
    numberColumn.setSortable(false);

    TableColumn<Concern, String> dateColumn = new TableColumn<>(Concern.DATE_HEADER);
    dateColumn.setCellValueFactory(param -> new SimpleStringProperty(
            param.getValue().getIssuedOn().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))));
    dateColumn.setPrefWidth(150);
    dateColumn.setSortable(false);

    tableViewConcern.getColumns().addAll(numberColumn, assignToColumn, clientColumn, categoryColumn, remarkColumn,
            dateColumn);
}
  • 4
    A service should do the db connection on a background thread and not freeze the GUI. Updating a `TableView` with 15 new items usually is not an issue either. Do you use cell(Value)Factorys that do long-running operations (e.g. fetching an image from the server based on the item)? Please post a [mcve]. – fabian Mar 16 '19 at 09:28
  • @fabian I have updated the example. The columns are either strings or long (id) – Jeremy Cruz Mar 16 '19 at 16:31
  • @fabian Thank you very much. I realize what was wrong I set the cell factory to call the database for every cell. – Jeremy Cruz Mar 16 '19 at 18:14

1 Answers1

0

The problem was every time the table updates it would call for the database.

    TableColumn<Concern, String> categoryColumn = new TableColumn<>(Concern.CATEGORY_HEADER);
    categoryColumn.setCellValueFactory(param -> new SimpleStringProperty(
            CategoryService.getInstance().getById(param.getValue().getCatergoryId()).getTitle())); //This part was the one that was making it lag
    categoryColumn.setMinWidth(150);
    categoryColumn.setSortable(false);

    TableColumn<Concern, String> assignToColumn = new TableColumn<>(Concern.EMPLOYEE_HEADER);
    assignToColumn.setCellValueFactory(param -> new SimpleStringProperty(
            UserAccountService.getInstance().getById(param.getValue().getUserAccountId()).getName())) ; //This part was the one that was making it lag
    assignToColumn.setMinWidth(125);
    assignToColumn.setSortable(false);

I solved it by making a local copy instead of having to call the database every time

Thanks Fabian