18/11/2024 - ZioCrick ha scritto:
Tra l'altro mi sono accorto che stavo già usando SwingWorker ;-) di cui il funzionamento mi resta comunque ancora un mistero… in particolare perché bisogna creare il server all'interno della doInBackground dove ricevo e spedisco i messaggi al client, e poi per devo usare la publish(String) per passare il codice alla process
Allora, cerco di spiegare un po' il funzionamento di SwingWorker.
Partiamo dal caso senza SwingWorker. Tu definisci un Runnable, crei il Thread e fai start(). Se all'interno del run() dovessi accedere alla UI, dovresti usare il “solito” noioso SwingUtilities.invokeLater per fare passare un pezzetto di codice nel EDT e aggiornare quindi es. un JLabel o altro. Ora immagina che il run() faccia la scansione in profondità del file-system per trovare dei file e (grazie magari ai velocissimi SSD) il codice trova centinaia/migliaia di file per ogni secondo che passa.
Se per ciascun file trovato tu facessi il invokeLater, il risultato è che la coda degli eventi si riempirebbe a dismisura solo per aggiornare la UI, che probabilmente verrebbe rallentata o comunque diventerebbe meno performante.
Bene, SwingWorker non solo permette di gestire un task in background ma semplifica l'aggiornamento della UI e lo fa in modo ottimale con un meccanismo di coalescing delle invocazioni del publish.
Quando estendi SwingWorker, l'unico metodo che sei obbligato a ridefinire (perché abstract) è il doInBackground. Se vuoi anche aggiornare la UI, puoi ridefinire il process. Se noti il publish ha un varargs:
protected final void publish(V... chunks)
mentre invece il process ha un List:
protected void process(List<V> chunks)
C'è un motivo ben preciso per questo. Il process viene invocato dal SwingWorker nel contesto del EDT. Quindi quando chiama la tua ridefinizione di process, lì dentro puoi tranquillamente aggiornate JLabel o quant'altro che vuoi.
La cosa bella è che NON fa per forza un process per ciascun publish ma, se necessario, “collassa” insieme più richieste di publish nel caso il process sia ancora in esecuzione. In pratica il publish si invoca tipicamente con 1 solo valore (o pochi, eventualmente), ecco il motivo del varargs. Ma se ne fai migliaia al secondo, se la UI è ancora in aggiornamento nel process, li accoda in una lista e li passa al process ad un giro successivo.
In pratica devi gestire una lista potenzialmente variabile di oggetti V. Se questi V fossero ad esempio dei java.io.File di cui mostrare il path su un JLabel, ti basta mostrare l'ultimo e sei a posto per non sovraccaricare inutilmente la UI.