Vaadin 对话框在方法执行之后而不是之前打开

Vaadin Dialog is opened after a method execution instead of before

当我单击一个按钮时,我想做两件事:首先,打开一个对话框,其次,执行一个方法(在 jar 文件中)。问题是,当我单击按钮时,首先执行该方法,然后打开对话框。代码是这样的:

button.addClickListener(event -> start()); 

public void start() { 
        dialog.open(); //Second, it opens the Dialog
        methodInJar(); //First it executes this method
    }

注意:无论是Dialog、Notification还是界面的任何变化,都会发生同样的事情。

有谁知道问题出在哪里?

谢谢。

PD。这是整个class:

package com.example.test;

import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.page.Push;
import com.vaadin.flow.router.Route;

@Route("myView")
@Push
public class MyView extends VerticalLayout {

    private UI ui;
    private Dialog dialog = new Dialog();

    public MyView(){

        addAttachListener(event -> {
            this.ui = event.getUI();
        });
        add(new Button("some button", click -> start()));
    }

    private void start(){
        this.ui.access(() -> {
            dialog.open();
        });
        methodInJarTest();
    }
    
    private void methodInJarTest() {
        try {
            System.out.println("JAR test - 10 seconds pause");
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

任何 UI 更改都是在到服务器的整个往返行程完成之后执行的,也就是在您的情况下按钮 clickListener 完全完成之后。而且因为在整个点击监听器期间,UI 被锁定,你甚至不能在点击监听器期间执行 ui.access,因为那也需要一个 UI 锁。

您在这里可以做的是让 clicklistener 启动一个新线程,您可以在其中执行繁重的工作。这意味着 clicklistener 很快就完成了,因此释放了它对 UI 的锁定。我们现在可以从仍然是 运行.

的后台线程中执行 ui.access(...) 调用

这是您的代码的样子

@Route("myView")
@Push
public class MyView extends VerticalLayout {

    private UI ui;
    private Dialog dialog = new Dialog();

    public MyView(){
        // save the ui instance when the view is attached for later reference
        addAttachListener(event -> {
            this.ui = event.getUI();
        });
        add(new Button("some button", click -> start()));
    }

    private void start(){
        new Thread(() -> {
            // UI.getCurrent() would return null in a new Thread, that's why we saved the ui instance during attach of the view.
            ui.access(() -> dialog.open());
            methodInJarTest();
        }).start();
    }

    private void methodInJarTest() {
        try {
            System.out.println("JAR test - 10 seconds pause");
            Thread.sleep(10000);
            ui.access(() -> dialog.add(new Span("methodInJar completed")));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

文档:
@Push
Asynchronous Updates

一般来说,您应该在后台线程中执行任何可能需要一段时间的任务,以避免锁定 UI。