【问题标题】:Vaadin Dialog is opened after a method execution instead of beforeVaadin 对话框在方法执行之后而不是之前打开
【发布时间】:2020-07-10 07:53:51
【问题描述】:

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

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

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

注意:无论是对话框、通知还是界面的任何变化,都会发生同样的事情。

有谁知道问题出在哪里?

谢谢。

PD。这是全班:

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();
        }
    }
}

【问题讨论】:

    标签: vaadin vaadin10


    【解决方案1】:

    任何 UI 更改都是在与服务器的整个往返完成后执行的,也就是在您的情况下,按钮 clickListener 完全完成之后。并且因为在整个 clicklistener 期间,UI 被锁定,你甚至不能在 click listener 期间执行ui.access,因为这也需要 UI-lock。

    您可以在这里做的是让 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。

    【讨论】:

    • 嗨,kscherrer。谢谢你快速的回复。我在我的项目中遵循了您的指示,但不幸的是问题仍然存在。我什至用你的代码创建了一个只有一个类的 Vaadin “my-starter-project”,但结果还是一样:一旦方法结束执行,它就会打开对话框。我正在使用 Eclipse 和 Vaadin 10+ 项目。当我创建项目时,技术堆栈是 Spring boot。任何想法?再次感谢。
    • 你能显示你视图的代码吗?也许我看到了问题所在。我在答案中编写的代码应该可以工作。
    • 当然,我已经编辑了我原来的问题。我正在一个仅包含一个类的项目上测试您的代码。谢谢。
    • 我自己试了一下代码,确实不行。我很困惑!显然,clicklistener 会完全锁定 ui 直到完成,因此 ui.access 被延迟,直到它自己可以锁定它。一种解决方案是将繁重的操作放在异步/后台线程中,这样 clicklistener 会很快完成,然后您从后台线程使用ui.access 执行 ui 更新。
    • 有效!感谢您的研究和帮助。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多