Диалог Vaadin открывается после выполнения метода, а не до - PullRequest
1 голос
/ 10 июля 2020

Когда я нажимаю кнопку, я хочу сделать 2 вещи: во-первых, открыть диалог, а во-вторых, выполнить метод (который находится в файле jar). Проблема в том, что, когда я нажимаю кнопку, сначала выполняется метод, а затем открывается диалоговое окно. Код выглядит примерно так:

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

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

Примечание. То же самое происходит независимо от того, является ли это диалогом, уведомлением или каким-либо изменением в интерфейсе.

Кто-нибудь знает, где находится проблема?

Спасибо.

ПД. Это целый класс:

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

1 Ответ

2 голосов
/ 10 июля 2020

Любые изменения пользовательского интерфейса выполняются после завершения всего обратного обращения к серверу, то есть после того, как кнопки clickListener полностью завершили работу в вашем случае. И поскольку в течение всего прослушивателя кликов пользовательский интерфейс заблокирован, вы даже не можете сделать ui.access во время прослушивателя кликов, потому что для этого также требуется блокировка пользовательского интерфейса.

Здесь вы можете сделать следующее: позвольте прослушивателю кликов начать новый поток, в котором вы выполняете тяжелую работу. Это означает, что прослушиватель кликов завершает работу очень быстро и поэтому снимает блокировку с пользовательского интерфейса. Теперь мы можем выполнять 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();
        }
    }
}

Документы: @ Pu sh Асинхронные обновления

В общем, можно сказать, что вы должны выполнять любую задачу, которая может занять некоторое время внутри фонового потока, чтобы избежать блокировки пользовательского интерфейса.

...