Back to blog
March 22, 2024
2 min read

Using Provider for State Management

Organize app logic with Provider

Using Provider for State Management

Provider is a recommended state management solution for Flutter applications. It offers a simple yet powerful way to manage application state and dependencies. This guide will show you how to effectively use Provider in your Flutter applications.

Why Choose Provider?

Provider offers several benefits:

  • Simple and intuitive API
  • Recommended by Flutter team
  • Minimal boilerplate code
  • Easy to test
  • Great performance

Core Concepts

  1. Provider Types

    • Provider
    • ChangeNotifierProvider
    • FutureProvider
    • StreamProvider
    • MultiProvider
  2. State Management Patterns

    • Single source of truth
    • Unidirectional data flow
    • Separation of concerns

Implementation

  1. Setup Provider

    // Add to pubspec.yaml
    dependencies:
      provider: ^latest_version
    
  2. Create a Model

    class CounterModel extends ChangeNotifier {
      int _count = 0;
    
      int get count => _count;
    
      void increment() {
        _count++;
        notifyListeners();
      }
    }
    
  3. Provide the Model

    void main() {
      runApp(
        ChangeNotifierProvider(
          create: (context) => CounterModel(),
          child: MyApp(),
        ),
      );
    }
    
  4. Consume the Provider

    class CounterWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Consumer<CounterModel>(
          builder: (context, counter, child) {
            return Text('Count: ${counter.count}');
          },
        );
      }
    }
    

Best Practices

  1. State Organization

    • Keep state close to where it’s used
    • Use multiple providers for different features
    • Avoid provider nesting when possible
  2. Performance Optimization

    • Use Consumer for specific widgets
    • Implement shouldNotify
    • Use Selector for fine-grained updates
  3. Testing

    void main() {
      testWidgets('Counter increments', (WidgetTester tester) async {
        await tester.pumpWidget(
          ChangeNotifierProvider(
            create: (_) => CounterModel(),
            child: MyApp(),
          ),
        );
    
        expect(find.text('Count: 0'), findsOneWidget);
        await tester.tap(find.byIcon(Icons.add));
        await tester.pump();
        expect(find.text('Count: 1'), findsOneWidget);
      });
    }
    

Common Use Cases

  1. User Authentication

    • Manage user state
    • Handle login/logout
    • Store user preferences
  2. Theme Management

    • Switch between themes
    • Store theme preferences
    • Apply theme changes
  3. API Integration

    • Manage API calls
    • Handle loading states
    • Store API responses

Conclusion

Provider is an excellent choice for state management in Flutter applications. Its simplicity and power make it suitable for both small and large applications. By following these guidelines and implementing the provided examples, you can create well-organized and maintainable Flutter applications.