如何使用线程导航到另一个 vaadin class UI

How to navigate to another vaadin class UI using thread

我创建了一个异步线程,通过向用户显示计时器(H1 标签)在 30 秒后从一个 UI class 导航到另一个 UI class .线程成功显示了 H1 标签的更新,但在 30 秒结束后没有导航到下一个 UI class。我收到 ui.navigate(ScoreBoard.class) 的错误异常调用 "java.lang.IllegalStateException: Cannot access state in VaadinSession or UI without locking the session.";打电话。

@Override
protected void onAttach(AttachEvent attachEvent) {
    // Start the data feed thread
    thread = new FeederThread(attachEvent.getUI(),timerc);
    thread.start();
}

//Thread
private static class FeederThread extends Thread {
    private final com.vaadin.flow.component.UI ui;
    private  final  H1 element;

    private int count = 30;


    public FeederThread(com.vaadin.flow.component.UI ui,H1 element) {
        this.ui = ui;
        this.element = element;
    }

    @Override
    public void run() {
        while (count>-1){
            try {
                Thread.sleep(1000);
                ui.access(()-> {
                    element.setText(String.valueOf(count)+" sec");
                });
                count--;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


        }
        //Exception in thread "Thread-46" java.lang.IllegalStateException: //Cannot access state in VaadinSession or UI without locking the session.
        ui.navigate(ScoreBoard.class);
    }
}

//线程中的异常 "Thread-46" java.lang.IllegalStateException: //在不锁定会话的情况下无法访问 VaadinSession 或 UI 中的状态。 ui.navigate(ScoreBoard.class);

UI.getCurrent() 在 Thread 中调用时返回 null,这是故意的。这样可以保证不返回错误的UI

例如,正确的模式是在您的视图中添加一个更新文本的方法。在该方法中,您可以使用 getUi().ifPresent(ui -> ui.access(..)) 。然后您可以安全地从 Thread 调用该方法。同样可以应用于导航。

或者,您可以将 ui 作为参数传递给您的线程,就像您所做的那样。当您这样做时,getCurrent() 调用已过时。

您需要在 class 中使用 @Push 启用推送。此外,由于导航操作是 UI 状态的一部分,因此您需要使用 UI.access。最后,如果您已经拥有该实例,则无需调用 getCurrent()。简而言之,这就是您所需要的:

...
@Push
public class MainView extends VerticalLayout {

    ...
        ui.access(() -> ui.navigate(ScoreBoard.class));
    ...
}