Menu
CoddyTech

Wybór miejsca przechowywania stanu

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

Przełącznik trybu ciemnego na ekranie Settings się przesuwa, ale nic nie staje się ciemne. Zachowuje swoją wartość dzięki setState, ale tylko przełącznik ma do niej dostęp. Motyw jest ustawiany w zupełnie innym miejscu — w MyApp. Ta wartość dotyczy całej aplikacji.

Każda wartość w aplikacji potrzebuje swojego miejsca. Zastanów się, kto z niej korzysta:

  • Jeden widżet (tekst pola, otwarty panel, indeks karty): setState w tym widżecie.
  • Kilka pobliskich widżetów (przycisk i etykieta obok niego): przenieś tę wartość do ich widżetu nadrzędnego i przekaż ją dalej.
  • Wiele widżetów lub kilka ekranów (użytkownik, koszyk, ustawienia): współdzielony model z Provider lub Riverpod.

Provider czy Riverpod? Oba rozwiązania spełniają swoje zadanie. Provider jest nieco prostszy i umieszcza modele w drzewie widżetów, gdzie można je znaleźć przez context. Riverpod przechowuje providery poza drzewem, więc wartość nie potrzebuje context, a providery mogą obserwować siebie nawzajem. Wybierz jedno rozwiązanie dla aplikacji i używaj go wszędzie.

W tym przypadku pasuje StateProvider: jedna wartość bool, odczytywana przez MyApp w celu wybrania motywu i zmieniana przez przełącznik:

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

// w MyApp, teraz ConsumerWidget:
themeMode: ref.watch(darkModeProvider) ? ThemeMode.dark : ThemeMode.light,
challenge icon

Wyzwanie

Trudny

Spraw, aby przełącznik trybu ciemnego zmieniał wygląd całej aplikacji:

  • Dodaj na górze final darkModeProvider = StateProvider((ref) => false);.
  • Zmień MyApp w widżet ConsumerWidget, którego themeMode zależy od dostawcy.
  • Zmień SettingsScreen w widżet ConsumerWidget: przełącznik wyświetla wartość dostawcy i ustawia ją po zmianie.

Spróbuj swoich sił

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 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