Dienstag, 7. April 2026

Vaadin Hintergrundprozesse mit Push

 Um ein TreeGrid effizient zu aktualisieren, ohne dass es flackert oder der User die Orientierung verliert, ist es am besten, das bestehende TreeData-Objekt zu modifizieren, anstatt ein komplett neues Set zu setzen.

Hier ist ein effizientes Muster für deine updateTree-Methode in der FileSystemView.

1. Die View-Methode (FileSystemView.java)

Diese Methode wird von deinem Service innerhalb von ui.access() aufgerufen.

Java
public void updateTree(VFSNode parentNode) {
    TreeData<VFSNode> treeData = treeGrid.getTreeData();

    // 1. Optional: Bestehende Kinder entfernen, um Duplikate zu vermeiden
    // Falls der Scan den Ast komplett neu aufbaut:
    treeData.removeItem(parentNode); // Entfernt Parent + alle Kinder
    treeData.addRootItems(parentNode); // Fügt Parent (neu) wieder ein

    // 2. Kinder des gescannten Nodes hinzufügen
    // Wir nehmen an, der VFSNode hat eine Liste seiner Kinder (files/folders)
    for (VFSNode child : parentNode.getChildren()) {
        treeData.addItem(parentNode, child);
    }

    // 3. WICHTIG: Den Provider benachrichtigen
    // refreshItem(node, true) aktualisiert den Node und rekursiv alle Kinder
    treeGrid.getDataProvider().refreshItem(parentNode, true);
    
    // Falls der Parent noch eingeklappt war, kannst du ihn direkt öffnen:
    treeGrid.expand(parentNode);
}

2. Der Service (Optimierter Scan)

Damit der UI-Thread nicht mit zu vielen kleinen Updates bombardiert wird (was die Performance drückt), sammeln wir die Daten im Hintergrund und "pushen" sie blockweise oder am Ende.

Java
@Async
public void scan(UI ui, FileSystemView view, VFSNode nodeToScan) {
    try {
        // SCHRITT 1: Die Arbeit im Hintergrund-Thread
        // Hier werden die Dateien auf der Festplatte gelesen und in das 
        // VFSNode-Objekt (Java POJO) geschrieben.
        List<VFSNode> discoveredFiles = fileSystemService.listDirectory(nodeToScan.getPath());
        nodeToScan.setChildren(discoveredFiles);

        // SCHRITT 2: Das UI-Update
        ui.access(() -> {
            // Jetzt übergeben wir den befüllten Node an die View
            view.updateTree(nodeToScan);
            Notification.show("Ordner " + nodeToScan.getName() + " aktualisiert.");
        });

    } catch (Exception e) {
        ui.access(() -> {
            Notification.show("Fehler beim Scannen: " + e.getMessage(), 
                              5000, Notification.Position.ERROR);
        });
    }
}

Warum diese Methode "effizient" ist:

  • refreshItem(item, true): Statt refreshAll() zu rufen (was den gesamten Baum im Browser neu zeichnet), sagst du Vaadin: "Nur dieser Ast hat sich geändert." Das spart massiv Bandbreite und Rechenpower im Browser.

  • Zustand bleibt erhalten: Wenn der User andere Äste des Baums geöffnet hat, bleiben diese offen. Ein refreshAll() klappt manchmal Äste zu, wenn der State nicht perfekt verwaltet wird.

  • Speichereffizienz: Du arbeitest direkt auf dem TreeData-Modell, das das Grid bereits kennt.

Profi-Tipp für große Verzeichnisse

Falls ein Ordner 10.000 Dateien hat:

Führe das ui.access() erst aus, wenn die Liste komplett ist. Wenn du jede Datei einzeln per ui.access() schickst, bekommt der Browser "Schluckauf", weil er 10.000-mal die UI synchronisieren muss.

Kleiner Check: Hast du in deinem VFSNode die Methoden equals() und hashCode() sauber überschrieben (z. B. basierend auf dem absoluten Pfad)? Das ist für TreeData lebenswichtig, damit es erkennt, welche Nodes identisch sind.

Soll ich dir ein Beispiel für eine saubere equals-Implementierung für deine File-Nodes geben?

Keine Kommentare:

Kommentar veröffentlichen