Menu
CoddyTech

Riverpod: Notifier

Część sekcji Zarządzanie stanem ścieżki Flutter w Coddy. Lekcja 19 z 27.

Do jednej liczby wystarczy StateProvider. Gdy stan podlega regułom, na przykład gdy jest listą z metodami dodawania i usuwania elementów, napisz Notifier: klasę, która przechowuje stan i metody, które go zmieniają.

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 zwraca pierwszy stan — pustą listę. Wewnątrz klasy state oznacza bieżącą wartość. GuestList.new to konstruktor klasy przekazywany dostawcy, aby mógł utworzyć powiadamiacz.

Najważniejsza zasada: przypisuj state nową wartość, nigdy nie zmieniaj starej. Riverpod powiadamia widżety tylko wtedy, gdy do state zostanie przypisany inny obiekt. state.add(name) zmienia listę w miejscu, więc state nadal wskazuje tę samą listę i nikt się o tym nie dowiaduje. [...state, name] tworzy nową listę: trzy kropki rozpakowują do niej wszystkie poprzednie imiona, a potem na końcu dodawane jest nowe.

Widżet wywołuje metodę za pośrednictwem powiadamiacza: ref.read(guestsProvider.notifier).add('Ada'). Ta strona używa ConsumerStatefulWidget, czyli widżetu ze stanem, ponieważ przechowuje również kontroler tekstu. Jego State ma pole ref.

challenge icon

Wyzwanie

Trudny

Lista gości wyświetla nazwy z guestsProvider, ale Add tylko czyści pole.

  • Dodaj metodę add(String name) do GuestList, która ustawia state na nową listę z nazwą na końcu.
  • Spraw, aby Add wywoływało tę metodę z tekstem z pola, zanim je wyczyści.

Spróbuj swoich sił

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 iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Zarządzanie stanem

Poćwicz samodzielnie: Kompilator Flutter online