Menu
CoddyTech

Mehrere Modelle: MultiProvider

Teil des Abschnitts State Management der Flutter-Journey von Coddy. Lektion 15 von 27.

Halte jedes Modell auf eine Sache beschränkt: die Punktzahl in einer Klasse, die Leben in einer anderen. Kleine Modelle sind leicht zu lesen, und ein Widget beobachtet nur, was es benötigt. Eine App mit mehreren Modellen benötigt mehrere Provider.

Du könntest sie verschachteln, sodass ein Provider das untergeordnete Element des nächsten ist, aber der Code rückt mit jedem Modell weiter nach rechts. MultiProvider nimmt stattdessen eine flache Liste entgegen:

runApp(
  MultiProvider(
    providers: [
      ChangeNotifierProvider(create: (context) => Score()),
      ChangeNotifierProvider(create: (context) => Lives()),
    ],
    child: const MyApp(),
  ),
);

Die Provider in der Liste haben kein eigenes child: MultiProvider stapelt sie für dich und setzt child unter alle. Jedes darunterliegende Widget kann jedes der Modelle beobachten oder auslesen, jeweils anhand seines Typs: context.watch<Lives>().

challenge icon

Aufgabe

Einfach

Die Spielseite beobachtet zwei Modelle, Score und Lives, aber main stellt nur den Punktestand bereit, daher zeigt die App einen Fehler an.

  • Ersetze den Provider in main durch einen MultiProvider, der beide Modelle bereitstellt.

Probier es selbst

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

class Score extends ChangeNotifier {
  int _points = 0;

  int get points => _points;

  void hit() {
    _points += 10;
    notifyListeners();
  }
}

class Lives extends ChangeNotifier {
  int _left = 3;

  int get left => _left;

  void miss() {
    if (_left > 0) {
      _left--;
      notifyListeners();
    }
  }
}

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => Score(),
      child: const MyApp(),
    ),
  );
}

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

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

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

  @override
  Widget build(BuildContext context) {
    final points = context.watch<Score>().points;
    final lives = context.watch<Lives>().left;
    return Scaffold(
      appBar: AppBar(title: Text('Lives: $lives')),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('Points: $points', style: const TextStyle(fontSize: 40)),
            const SizedBox(height: 16),
            Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                ElevatedButton(
                  onPressed: () => context.read<Score>().hit(),
                  child: const Text('Hit'),
                ),
                const SizedBox(width: 16),
                ElevatedButton(
                  onPressed: () => context.read<Lives>().miss(),
                  child: const Text('Miss'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in State Management

Übe selbstständig: Online-Flutter-Compiler