Flutter: widget ovunque

Nel post precedente abbiamo modificato una semplice app per giocare un po' con il tema dell'applicazione. Anche se non ho sottolineato l'argomento, nella nostra app non abbiamo fatto altro che utilizzare semplici oggetti combinati o nidificati per ottenere quanto volevamo, i mattoni delle applicazioni Flutter: i widget.


Il modello su cui si basa Flutter può essere descritto con una semplice asserzione: tutto è un widget. In effetti tutto ciò che si definisce o si utilizza in Flutter è un widget.

I widget sono i componenti base di un’applicazione Flutter, formano una struttura gerarchica nella quale vengono ereditate le caratteristiche del widget genitore, come ci si aspetta in stile OOP, permettono di definire ogni elemento di una applicazione in Flutter, compresa la stessa app (testi, box contenitori, immagini e altro). Un widget può avere o meno uno stato, che ne può determinare contenuto o forma. Un widget potrebbe essere visto come un oggetto, una struttura presente in moltissimi linguaggi, con la differenza che può avere uno stato per aggiornare la view e può contenere contenuti, definire forme, proprietà e metodi. Infine un widget può includere o estendere un altro widget. Quindi un’applicazione in Flutter è ottenuta dalla composizione di widget. Un esempio può essere un form che contiene un widget di input text ecc. e un botton anch’esso widget.

Nelle versioni attuali di Flutter è possibile definire due diversi tipi di widget: Stateless WidgetStateful Widget:

Stateless widget

Sono widget privi di stato (statelesswidget): sono immutabili, come una classe statica, perchè una volta creati, gli stateless widget non subiranno alcuna variazione e non modificheranno il proprio comportamento nemmeno in base a eventi o azioni dell’utente. Ad esempio, un'etichetta di testo che non cambia mai può essere definita utilizzando un widget statico.

Un esempio semplice di definizione di un stateless widget è questo


class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

e si ottiene estendendo la classe StatelessWidget e dove  il metodo build() viene invocato solo la prima volta che il widget viene inserito nel widget tree o quando le dipendenze del widget cambiano.

Da ciò si evince che le proprietà di uno StatelessWidget sono immutabili e l’unico modo per modificarle è la creazione di una nuova istanza di quel widget.

Un esempio di applicazione costruita Stateless widget è l'app Hello World dei post precedenti.

Stateful widget

Sono widget dinamici dotati di stato (statefulwidget): una o più proprietà possono cambiare durante l'esecuzione dell'app determinando un cambio di comportamento o di aspetto o di funzionalità del widget, come ad esempio una schermata dell’app che cambia in base al valore di una variabile. Per aggiornare il widget è necessario utilizzare il setstate con la proprietà aggiornata in modo che venga propagata la modifica.

Un esempio semplice di definizione di un stateless widget è questo (il codice è quello che viene generato in modo automatico quando si crea un nuovo progetto Flutter):


class Counter extends StatefulWidget {
  Counter({Key key}) : super(key: key);
  @override
  _CounterState createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int _counter = 0;
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Esempio StatefulWidget'),
      ),
      body: Center(
          child: Text(
            '$_counter',
            style: TextStyle(fontSize: 30),
          )
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        child: Icon(Icons.add),
      ),
    );
  }
}

e si ottiene estendendo la classe StatefulWidget e dove  il metodo build() viene invocato sia la prima volta che il widget viene inserito nel widget tree o quando le dipendenze del widget cambiano, ma anche tutte le volte che viene chiamata la funzione setState(), che nel caso specifico, viene richiamata a sua volta ad ogni pressione sul tasto definito con il widget FloatingActionButton

Quale usare: Stateless o Stateful widget ?

La domanda da farsi ora è: quale tipo devo utilizzare nelle mie applicazioni ? 

La risposta dipende da cosa stiamo realizzando, ma in generale, se nella nostra app abbiamo bisogno di un widget che cambia per effetto di una variabile, o per l'interazione con l'utente o altri casi simili, sarà necessario utilizzare un Stateful widget, altrimenti sarà sufficiente un Stateless widget. Realisticamente in una app utilizzeremo entrambi i tipi, probabilmente nidificati l'uno nell'altro.

Ad esempio, immaginiamo di trovarci di fronte ad un applicazione che mostra un elenco di titoli di libri con la possibilità di indicare quelli preferiti e una scheda di dettaglio per ognuno. Sicuramente per evidenziare se sul singolo titolo abbiamo attivato preferito o no, occorrerà utilizzare uno Stateful widget, ma per costruire la scheda (statica) di dettaglio (con la visualizzazione della copertina, dell'autore, dell'anno di pubblicazione, ...) saranno sufficienti dei Stateless widget.

Nei prossimi articoli vedremo nel dettaglio alcuni tipi di widget e il modo in cui usarli.

Commenti