Logo

The Unbound Academy

Flutter Multi-Platform Development

Flutter Riverpod State Management

Flutter
Riverpod

Using StateProvider

Follow these steps to use StateProvider in Flutter:

  1. Add Riverpod to Your Project

    In your pubspec.yaml, add the Riverpod dependency:

    dependencies:
    flutter_riverpod: ^2.0.0

    Run:

    flutter pub get
  2. Create a State Provider

    Create a new file for your state, e.g., counter_provider.dart:

    import 'package:flutter_riverpod/flutter_riverpod.dart';
    
    // Define a StateProvider for the counter
    final counterProvider = StateProvider<int>((ref) => 0);
  3. Use the Provider in a Widget

    In your UI file, access and modify the state using the provider:

    import 'package:flutter/material.dart';
    import 'package:flutter_riverpod/flutter_riverpod.dart';
    import 'counter_provider.dart';
    
    class CounterScreen extends ConsumerWidget {
    @override
    Widget build(BuildContext context, WidgetRef ref) {
      final counter = ref.watch(counterProvider);
    
      return Scaffold(
        appBar: AppBar(title: Text('Counter')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text('Counter Value: $counter', style: TextStyle(fontSize: 24)),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  ref.read(counterProvider.notifier).state++;
                },
                child: Text('Increment'),
              ),
            ],
          ),
        ),
      );
    }
    }
  4. Wrap Your App with ProviderScope

    In your main.dart, wrap the app with ProviderScope to enable Riverpod:

    import 'package:flutter/material.dart';
    import 'package:flutter_riverpod/flutter_riverpod.dart';
    import 'counter_screen.dart';
    
    void main() {
    runApp(ProviderScope(child: MyApp()));
    }
    
    class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        home: CounterScreen(),
      );
    }
    }
  5. Split Across Multiple Files

    Organize your project by splitting providers and UI files:

    • State Management: Keep all providers in one folder (e.g., providers/).
    • UI Files: Separate each screen into its own file and import the needed provider.

    Example:

    • lib/providers/counter_provider.dart
    • lib/screens/counter_screen.dart
  6. Explanation of Concepts

    • StateProvider: Manages a single value (like an integer or string).
    • ref.watch: Reads the current state and rebuilds the widget when the state changes.
    • ref.read: Accesses the state without rebuilding the widget.
    • ref.read(provider.notifier).state: Modifies the state.
  7. Test and Extend

    You can add more providers (e.g., StateNotifierProvider for complex logic) and access them across different files to maintain a global state.


Using StateNotifierProvider

Follow these steps to use StateNotifierProvider in Flutter:

  1. Create a StateNotifier

    Create a new file, e.g., counter_notifier.dart:

    import 'package:flutter_riverpod/flutter_riverpod.dart';
    
    class CounterNotifier extends StateNotifier<int> {
    CounterNotifier() : super(0);
    
    void increment() => state++;
    void decrement() => state--;
    }
  2. Create a StateNotifierProvider

    In the same file or another file, define the provider:

    final counterNotifierProvider = StateNotifierProvider<CounterNotifier, int>(
    (ref) => CounterNotifier(),
    );
  3. Use the Provider in a Widget

    import 'package:flutter/material.dart';
    import 'package:flutter_riverpod/flutter_riverpod.dart';
    import 'counter_notifier.dart';
    
    class CounterScreen extends ConsumerWidget {
    @override
    Widget build(BuildContext context, WidgetRef ref) {
      final counter = ref.watch(counterNotifierProvider);
    
      return Scaffold(
        appBar: AppBar(title: Text('Counter with StateNotifier')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text('Counter Value: $counter', style: TextStyle(fontSize: 24)),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  ElevatedButton(
                    onPressed: () {
                      ref.read(counterNotifierProvider.notifier).increment();
                    },
                    child: Text('Increment'),
                  ),
                  SizedBox(width: 20),
                  ElevatedButton(
                    onPressed: () {
                      ref.read(counterNotifierProvider.notifier).decrement();
                    },
                    child: Text('Decrement'),
                  ),
                ],
              ),
            ],
          ),
        ),
      );
    }
    }
  4. Wrap Your App with ProviderScope

    import 'package:flutter/material.dart';
    import 'package:flutter_riverpod/flutter_riverpod.dart';
    import 'counter_screen.dart';
    
    void main() {
    runApp(ProviderScope(child: MyApp()));
    }
    
    class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        home: CounterScreen(),
      );
    }
    }