导航到新视图后,我想启动一个后台线程,它会对我的视图进行一些验证并报告更改。我正在构建ui并在AfterNavigationObserver#afterNavigation
上启动线程。
大多数情况下,这是有效的,但当后台线程完成得太快时,它无法更新视图,因为渲染尚未完成,要更新的组件还不可见。可能的解决方案是在渲染完成并且视图在浏览器中可见后启动背景线程。建议的方法是什么?我查看了API,但找不到匹配的事件。
使用vaadin流量14.8。
在下面的最小示例中,第二个手风琴面板应在任务完成时打开。它在我的电脑上工作,大多超时500毫秒或更长时间。低于此值或取消睡眠会导致无法打开第二个手风琴。
视图:
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.accordion.Accordion;
import com.vaadin.flow.component.accordion.AccordionPanel;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.page.Push;
import com.vaadin.flow.router.AfterNavigationEvent;
import com.vaadin.flow.router.AfterNavigationObserver;
import com.vaadin.flow.router.Route;
import de.fs_aut.ddm.desktop.bgtasks.TimeConsumingTask;
import org.springframework.beans.factory.annotation.Autowired;
@Route("debug")
@Push
public class DebugView extends VerticalLayout implements AfterNavigationObserver {
@Autowired
private TimeConsumingTask task;
private UI ui;
private Accordion acc;
private AccordionPanel firstPanel;
private AccordionPanel secondPanel;
@Override
public void afterNavigation(AfterNavigationEvent event) {
removeAll();
acc = new Accordion();
firstPanel = new AccordionPanel("First task", new Label("first task in progress"));
secondPanel = new AccordionPanel("second task", new Label("second task in progress"));
acc.add(firstPanel);
acc.add(secondPanel);
add(acc);
startValidation();
}
public void startValidation() {
ui = UI.getCurrent();
task.sleep().addCallback(result -> {
ui.access(() -> {
acc.open(secondPanel);
});
}, error -> {
});
}
}
异步任务:
import java.time.LocalDateTime;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.util.concurrent.ListenableFuture;
/**
* Testdummy. Does nothing but waits.
*
*/
@Service
public class TimeConsumingTask {
@Async
public ListenableFuture<String> sleep() {
try {
Thread.sleep(500);
} catch (final InterruptedException e) {
e.printStackTrace();
}
return AsyncResult.forValue("Validation finished at " + LocalDateTime.now().toString());
}
}
您可以尝试在路由上覆盖并实现onAttach。看见https://vaadin.com/docs/v14/flow/creating-components/tutorial-component-lifecycle-callbacks了解更多详细信息。
Knoobie的答案应该被检查,但(如果我没记错的话(StackOverflow准则更喜欢代码而不是链接。
每个CCD_ 2采用CCD_ 3方法。来自Javadoc:
`protected void onAttach(AttachEvent AttachEvent(
当组件附加到UI时调用。
默认实现不执行任何操作。
在为组件激发AttachEvent之前调用此方法。
参数:
attachEvent-附加事件
您可以在任何Component
:中覆盖此方法
public class MyComponent extends VerticalLayout {
@Override
protected void onAttach(AttachEvent event) {
System.out.println("I attached: " + event);
}
}
Component
还实现了AttachNotifier
,它提供了以下方法:
public class MyComponent extends VerticalLayout {
public MyComponent() {
addAttachListener(event -> System.out.println("I attached: " + event));
}
}
注意上面引用的文档!onAttach
方法在事件之前被调用。
另一种方法是从JavaScript中等待v-loading-indicator
的第一个子代拥有display: none
。