Menu
CoddyTech

בחירת המקום שבו המצב נשמר

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

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

כל ערך באפליקציה זקוק למקום משלו. שאלו מי משתמש בו:

  • רכיב אחד (טקסט של שדה, לוח פתוח, אינדקס של כרטיסייה): setState באותו רכיב.
  • כמה רכיבים סמוכים (כפתור והתווית שלצדו): מעלים את הערך לרכיב האב שלהם ומעבירים אותו הלאה.
  • רכיבים רבים או כמה מסכים (המשתמש, עגלת קניות, ההגדרות): מודל משותף באמצעות Provider או Riverpod.

Provider או Riverpod? שניהם עושים את העבודה. Provider מעט פשוט יותר וממקם מודלים בעץ הרכיבים, שם אפשר למצוא אותם באמצעות context. Riverpod שומר את הספקים מחוץ לעץ, כך שערך אינו זקוק ל־context, וספקים יכולים לעקוב זה אחר זה. בחרו אחד עבור האפליקציה והשתמשו בו בכל מקום.

כאן מתאים StateProvider: ערך bool אחד, שנקרא על ידי MyApp כדי לבחור את ערכת הנושא ומשתנה על ידי המתג:

final darkModeProvider = StateProvider((ref) => false);

// בתוך MyApp, שכעת הוא ConsumerWidget:
themeMode: ref.watch(darkModeProvider) ? ThemeMode.dark : ThemeMode.light,
challenge icon

אתגר

קשה

הפוך את מתג המצב הכהה לכזה שמשנה את כל האפליקציה:

  • הוסף בראש הקובץ את final darkModeProvider = StateProvider((ref) => false);.
  • הפוך את MyApp ל־ConsumerWidget שה־themeMode שלו נקבע בהתאם לספק.
  • הפוך את SettingsScreen ל־ConsumerWidget: המתג מציג את ערך הספק ומעדכן אותו כשהערך משתנה.

נסו בעצמכם

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      themeMode: ThemeMode.light,
      home: const HomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Notes'),
        actions: [
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const SettingsScreen()),
              );
            },
          ),
        ],
      ),
      body: const Center(child: Text('No notes yet')),
    );
  }
}

class SettingsScreen extends StatefulWidget {
  const SettingsScreen({super.key});

  @override
  State<SettingsScreen> createState() => _SettingsScreenState();
}

class _SettingsScreenState extends State<SettingsScreen> {
  bool dark = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Settings')),
      body: ListView(
        children: [
          SwitchListTile(
            title: const Text('Dark mode'),
            value: dark,
            onChanged: (value) {
              setState(() {
                dark = value;
              });
            },
          ),
        ],
      ),
    );
  }
}
quiz iconבחנו את עצמכם

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

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

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