Last active
October 2, 2024 11:40
-
-
Save TatuLund/e8dc7e1c7b1504db501e05cd3368370f to your computer and use it in GitHub Desktop.
This is an example of LazyComponent for Vaadin 14/23/24. If the content creation of the component takes long. For example data needs to be fetched from the back end and computed, or it is an image whose loading takes time, one may need to produce the component in background process. This example component wraps the process in the Future which cr…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * This is an example of LazyComponent for Vaadin 14/23/24. If the content creation | |
| * of the component takes long. For example data needs to be fetched from the back | |
| * end and computed, or it is an image whose loading takes time, one may need to | |
| * produce the component in background process. This example component wraps the | |
| * process in the Future which creates the component and upon completion adds to | |
| * view. @Push annotation needs to be present in AppShellConfigurator. | |
| */ | |
| package com.example.application.views; | |
| import java.util.List; | |
| import java.util.Random; | |
| import java.util.concurrent.CompletableFuture; | |
| import java.util.concurrent.Executor; | |
| import java.util.concurrent.Executors; | |
| import java.util.stream.Collectors; | |
| import java.util.stream.IntStream; | |
| import com.vaadin.flow.component.AttachEvent; | |
| import com.vaadin.flow.component.Component; | |
| import com.vaadin.flow.component.Composite; | |
| import com.vaadin.flow.component.DetachEvent; | |
| import com.vaadin.flow.component.HasSize; | |
| import com.vaadin.flow.component.grid.Grid; | |
| import com.vaadin.flow.component.html.Div; | |
| import com.vaadin.flow.component.progressbar.ProgressBar; | |
| import com.vaadin.flow.function.SerializableSupplier; | |
| import com.vaadin.flow.router.Route; | |
| import com.vaadin.flow.shared.communication.PushMode; | |
| import com.vaadin.flow.theme.lumo.LumoUtility; | |
| @SuppressWarnings("serial") | |
| @Route(value = "lazy-component", layout = MainLayout.class) | |
| public class LazyComponentView extends Div { | |
| Executor executor = Executors.newSingleThreadExecutor(); | |
| Random random = new Random(); | |
| public LazyComponentView() { | |
| LazyComponent<Grid<String>> div = new LazyComponent<>(executor, | |
| () -> produceGrid()); | |
| div.setWidth("800px"); | |
| div.setHeight("500px"); | |
| div.addClassNames(LumoUtility.BoxShadow.SMALL, LumoUtility.Border.ALL, | |
| LumoUtility.BorderColor.CONTRAST_20); | |
| add(div); | |
| } | |
| public Grid<String> produceGrid() { | |
| try { | |
| // Simulating a long task | |
| Thread.sleep(5000); | |
| } catch (InterruptedException e) { | |
| } | |
| Grid<String> grid = new Grid<>(); | |
| List<String> items = IntStream.range(0, 10000) | |
| .mapToObj(i -> "String " + random.nextInt(10000)) | |
| .collect(Collectors.toList()); | |
| grid.addColumn(item -> item.toString()); | |
| grid.setItems(items); | |
| grid.setHeight("100%"); | |
| return grid; | |
| } | |
| public static class LazyComponent<T extends Component> | |
| extends Composite<Div> implements HasSize { | |
| CompletableFuture<T> future; | |
| Executor executor; | |
| SerializableSupplier<T> task; | |
| public LazyComponent(Executor executor, SerializableSupplier<T> task) { | |
| this.executor = executor; | |
| this.task = task; | |
| addClassNames(LumoUtility.Display.FLEX); | |
| } | |
| @Override | |
| protected void onAttach(AttachEvent event) { | |
| ProgressBar bar = new ProgressBar(); | |
| bar.setIndeterminate(true); | |
| bar.addClassName(LumoUtility.AlignSelf.CENTER); | |
| getContent().add(bar); | |
| if (getUI().get().getPushConfiguration() | |
| .getPushMode() != PushMode.AUTOMATIC) { | |
| throw new IllegalStateException( | |
| "Push updates require Push to be enabled and PushMode.AUTOMATIC"); | |
| } | |
| future = CompletableFuture.supplyAsync(task, executor); | |
| future.thenAccept(component -> { | |
| var ui = event.getUI(); | |
| if (ui != null) { | |
| ui.access(() -> getContent().replace(bar, component)); | |
| } | |
| }); | |
| } | |
| @Override | |
| protected void onDetach(DetachEvent event) { | |
| if (future != null && !future.isDone()) { | |
| future.cancel(true); | |
| } | |
| future = null; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment