Menu
CoddyTech

Provider, die andere Provider beobachten

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

Einige Zustände ergeben sich aus anderen Zuständen: Die Gesamtminuten sind die Summe der Trainingseinheiten. Du könntest sie in jedem Widget addieren, das eine Gesamtsumme anzeigt, oder die Berechnung einmal schreiben – als Provider, der einen anderen Provider beobachtet:

final totalMinutesProvider = Provider((ref) {
  final workouts = ref.watch(workoutsProvider);
  return workouts.fold(0, (sum, w) => sum + w.minutes);
});

Die Funktion eines Providers erhält ebenfalls ein ref. Wenn du darin ref.watch verwendest, merkt sich Riverpod, dass die Gesamtminuten von den Trainingseinheiten abhängen. Fügst du eine Trainingseinheit hinzu, werden die Gesamtminuten erneut berechnet, und jedes Widget, das sie beobachtet, wird neu aufgebaut.

Verwende hier ref.watch, nicht ref.read. Mit read wird die Liste einmal abgerufen, wenn die Gesamtminuten zum ersten Mal berechnet werden, und danach ändern sie sich nie wieder.

Das ist die Getter-Idee von vorhin, übertragen auf die ganze App: Speichere so wenig wie möglich und berechne den Rest daraus.

challenge icon

Aufgabe

Mittel

Die obere Leiste beobachtet totalMinutesProvider, aber dieser Provider gibt immer 0 zurück.

  • Lass sie workoutsProvider beobachten und die Summe der minutes aller Workouts zurückgeben.

Probier es selbst

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

class Workout {
  Workout(this.name, this.minutes);

  final String name;
  final int minutes;
}

class WorkoutLog extends Notifier<List<Workout>> {
  @override
  List<Workout> build() => [];

  void add(Workout workout) {
    state = [...state, workout];
  }
}

final workoutsProvider = NotifierProvider<WorkoutLog, List<Workout>>(WorkoutLog.new);

final totalMinutesProvider = Provider((ref) {
  return 0;
});

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: LogPage(),
    );
  }
}

class LogPage extends ConsumerWidget {
  const LogPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final workouts = ref.watch(workoutsProvider);
    final total = ref.watch(totalMinutesProvider);
    return Scaffold(
      appBar: AppBar(title: Text('Total: $total min')),
      body: Column(
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () => ref.read(workoutsProvider.notifier).add(Workout('Run', 30)),
                child: const Text('Run'),
              ),
              const SizedBox(width: 16),
              ElevatedButton(
                onPressed: () => ref.read(workoutsProvider.notifier).add(Workout('Yoga', 20)),
                child: const Text('Yoga'),
              ),
            ],
          ),
          Expanded(
            child: ListView(
              children: [
                for (final w in workouts) ListTile(title: Text(w.name), trailing: Text('${w.minutes} min')),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
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