Menu
CoddyTech

Riverpod: Notifier

חלק מהיחידה ניהול מצב במסלול ה-Flutter של Coddy. שיעור 19 מתוך 27.

StateProvider מתאים למספר אחד. כשהמצב מגיע עם כללים, כמו רשימה עם מתודות להוספה ולהסרה, כותבים Notifier: מחלקה שמחזיקה את המצב ואת המתודות שמשנות אותו.

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 מחזירה את המצב הראשוני, רשימה ריקה. בתוך המחלקה, state הוא הערך הנוכחי. GuestList.new הוא הבנאי של המחלקה, שמועבר לספק כדי שיוכל ליצור את ה-notifier.

הכלל המרכזי: נותנים ל-state ערך חדש, לעולם לא משנים את הערך הישן. Riverpod מודיע לווידג'טים רק כאשר state מקבל אובייקט אחר. state.add(name) משנה את הרשימה במקום, כך ש-state עדיין מצביע לאותה רשימה ואיש לא מקבל על כך הודעה. [...state, name] יוצרת רשימה חדשה: שלוש הנקודות מפזרות לתוכה כל שם ישן, ואז השם החדש מתווסף בסוף.

ווידג'ט קורא למתודה דרך ה-notifier: ref.read(guestsProvider.notifier).add('Ada'). הדף הזה הוא ConsumerStatefulWidget, מהסוג ששומר מצב, כי הוא גם שומר בקר טקסט. ל-State שלו יש את ref כשדה.

challenge icon

אתגר

קשה

רשימת האורחים מציגה את השמות שב־guestsProvider, אבל Add רק מנקה את השדה.

  • הוסף ל־GuestList מתודה בשם add(String name) שמציבה ב־state רשימה חדשה, כשהשם מופיע בסופה.
  • גרום ל־Add לקרוא למתודה עם הטקסט שבשדה, לפני שהיא מנקה את השדה.

נסו בעצמכם

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 iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה ניהול מצב

תרגלו בעצמכם: קומפיילר Flutter אונליין