Menu
CoddyTech
flag Ar iconالعربيةdown icon

المزوّدات التي تراقب المزوّدات

جزء من قسم إدارة الحالة في رحلة Flutter على Coddy. الدرس 20 من 27.

تنشأ بعض الحالات من حالات أخرى: فإجمالي الدقائق هو مجموع التمارين. يمكنك جمعها في كل عنصر واجهة مستخدم يعرض الإجمالي، أو كتابتها مرة واحدة، كمزوّد يراقب مزوّدًا آخر:

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

تتلقى دالة المزوّد أيضًا ref. باستخدام ref.watch بداخلها، يتذكر Riverpod أن الإجمالي يعتمد على التمارين. أضف تمرينًا، وسيُعاد حساب الإجمالي، وستُعاد إعادة بناء كل عناصر واجهة المستخدم التي تراقب الإجمالي.

استخدم ref.watch هنا، وليس ref.read. يأخذ read القائمة مرة واحدة، عند حساب الإجمالي لأول مرة، ولا يتغير الإجمالي بعد ذلك أبدًا.

هذه هي فكرة أداة الوصول من قبل، على مستوى التطبيق كله: خزّن أقل قدر ممكن، واستنتج الباقي منه.

challenge icon

التحدي

متوسط

يراقب الشريط العلوي totalMinutesProvider، لكن هذا المزوّد يُرجع دائمًا 0.

  • اجعله يراقب workoutsProvider ويُرجع مجموع دقائق كل تمرين باستخدام minutes.

جرّب بنفسك

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 iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس إدارة الحالة

تدرّب بنفسك: مترجم Flutter عبر الإنترنت