Menu
CoddyTech

Riverpod: Notifier

Fa parte della sezione Gestione dello stato del percorso Flutter di Coddy. Lezione 19 di 27.

Un StateProvider va bene per un numero. Quando lo stato è accompagnato da regole, come un elenco con metodi per aggiungere e rimuovere elementi, scrivi un Notifier: una classe che contiene lo stato e i metodi che lo modificano.

class GuestList extends Notifier<List<String>> {
  @override
  List<String> build() => [];

  void add(String name) {
    state = [...state, name];
  }
}

final guestsProvider =
    NotifierProvider<GuestList, List<String>>(GuestList.new);

build restituisce lo stato iniziale, un elenco vuoto. All'interno della classe, state è il valore corrente. GuestList.new è il costruttore della classe, passato al provider affinché possa creare il notifier.

La regola fondamentale: assegna a state un nuovo valore, non modificare mai quello vecchio. Riverpod avvisa i widget solo quando a state viene assegnato un oggetto diverso. state.add(name) modifica l'elenco sul posto, quindi state è ancora lo stesso elenco e nessuno ne viene informato. [...state, name] crea un nuovo elenco: i tre puntini ne copiano tutti i vecchi nomi, poi quello nuovo viene aggiunto alla fine.

Un widget chiama un metodo tramite il notifier: ref.read(guestsProvider.notifier).add('Ada'). Questa pagina è un ConsumerStatefulWidget, il tipo con stato, perché mantiene anche un controller di testo. Il suo State ha ref come campo.

challenge icon

Sfida

Difficile

La lista degli invitati mostra i nomi in guestsProvider, ma Add si limita a svuotare il campo.

  • Aggiungi a GuestList un metodo add(String name) che imposti state su una nuova lista con il nome in fondo.
  • Fai in modo che Add lo chiami con il testo del campo, prima di svuotare il campo.

Provalo tu

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class GuestList extends Notifier<List<String>> {
  @override
  List<String> build() => [];
}

final guestsProvider = NotifierProvider<GuestList, List<String>>(GuestList.new);

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: PartyPage(),
    );
  }
}

class PartyPage extends ConsumerStatefulWidget {
  const PartyPage({super.key});

  @override
  ConsumerState<PartyPage> createState() => _PartyPageState();
}

class _PartyPageState extends ConsumerState<PartyPage> {
  final controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    final guests = ref.watch(guestsProvider);
    return Scaffold(
      appBar: AppBar(title: Text('Guests: ${guests.length}')),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(16),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: controller,
                    decoration: const InputDecoration(labelText: 'Guest name'),
                  ),
                ),
                const SizedBox(width: 8),
                ElevatedButton(
                  onPressed: () {
                    controller.clear();
                  },
                  child: const Text('Add'),
                ),
              ],
            ),
          ),
          Expanded(
            child: ListView(
              children: [
                for (final name in guests) ListTile(leading: const Icon(Icons.person), title: Text(name)),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Gestione dello stato

Esercitati da solo: Compilatore Flutter online