How to Use Riverpod in Flutter with Full Example (2025)

Introduction

State management is one of the most essential aspects of building efficient Flutter applications. In 2025, Riverpod continues to be one of the most popular and reliable state management libraries in Flutter development. Whether you’re building a small app or a large-scale production application, Riverpod offers a modern, safe, and testable approach to managing your app state.

In this article, we’ll explore how to use Riverpod in Flutter, walk through a full example, and explain real-life use cases where Riverpod truly shines.

What is Riverpod?

Riverpod is a robust state management solution for Flutter applications, created by Remi Rousselet (also the author of Provider). Unlike Provider, Riverpod is:

  • Compile-time safe
  • Completely testable
  • IDE-friendly (auto-complete and refactoring support)
  • Free from context limitations (can access state from anywhere)

Riverpod helps separate business logic from UI, which is critical for large and maintainable codebases.

Why Use Riverpod in 2025?

In 2025, with the increasing complexity of Flutter apps, Riverpod offers:

  • Scalable architecture suitable for enterprise apps
  • Code safety with type-checking
  • Better performance through granular rebuilds
  • Enhanced testing experience with no dependency on Flutter widgets

Real-Life Use Case: Task Manager App

Let’s assume you are building a Task Manager App that allows users to add, update, and delete tasks.

Step-by-Step Riverpod Example in Flutter

Step 1: Install Riverpod

In your pubspec.yaml file:

dependencies:
flutter:
sdk: flutter
flutter_riverpod: ^2.4.0

Run:

flutter pub get

Step 2: Create a Model

class Task {
final String id;
final String title;
final bool isDone;

Task({required this.id, required this.title, this.isDone = false});
}

Step 3: Create a StateNotifierProvider

import 'package:flutter_riverpod/flutter_riverpod.dart';

class TaskNotifier extends StateNotifier<List<Task>> {
TaskNotifier() : super([]);

void addTask(String title) {
final newTask = Task(id: DateTime.now().toString(), title: title);
state = [...state, newTask];
}

void toggleTask(String id) {
state = [
for (final task in state)
if (task.id == id)
Task(id: task.id, title: task.title, isDone: !task.isDone)
else
task
];
}

void removeTask(String id) {
state = state.where((task) => task.id != id).toList();
}
}

final taskProvider = StateNotifierProvider<TaskNotifier, List<Task>>((ref) {
return TaskNotifier();
});

Step 4: Setup ProviderScope

In main.dart:

void main() {
runApp(ProviderScope(child: MyApp()));
}

Step 5: Use Provider in UI

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

class HomeScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final tasks = ref.watch(taskProvider);
final taskNotifier = ref.read(taskProvider.notifier);

return Scaffold(
appBar: AppBar(title: Text('Task Manager')),
body: ListView.builder(
itemCount: tasks.length,
itemBuilder: (_, index) {
final task = tasks[index];
return ListTile(
title: Text(
task.title,
style: TextStyle(
decoration: task.isDone ? TextDecoration.lineThrough : null,
),
),
leading: Checkbox(
value: task.isDone,
onChanged: (_) => taskNotifier.toggleTask(task.id),
),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => taskNotifier.removeTask(task.id),
),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => taskNotifier.addTask('New Task'),
child: Icon(Icons.add),
),
);
}
}

Key Features of Riverpod

  • Global state management without BuildContext
  • Immutable state updates via StateNotifier
  • Support for async with FutureProvider and StreamProvider
  • Auto-dispose logic for memory management
  • Scoped overrides for testing or custom configuration

Read Articles : flutter_bloc Package in Flutter – Features & Use Cases [2025 Edition]

When Should You Use Riverpod?

  • Building apps with complex state transitions
  • Developing modular and scalable Flutter projects
  • Creating test-driven Flutter applications
  • When you need clean separation of concerns

FAQs About Riverpod

Q: What is the difference between Provider and Riverpod?

Riverpod is the improved, compile-safe, context-independent version of Provider. It avoids many limitations of the original Provider package.

Q: Can I use Riverpod with Flutter Hooks?

Yes, hooks_riverpod allows seamless integration of Riverpod with hooks for cleaner widget code.

Q: Is Riverpod good for large projects?

Absolutely. Riverpod was designed with scalability and testability in mind, making it ideal for enterprise apps.

Q: How to manage async operations using Riverpod?

Use FutureProvider or StreamProvider to fetch data asynchronously, and watch the state using ref.watch().

Q: Does Riverpod work with GetX or BLoC?

Riverpod is a complete state management solution and doesn’t require pairing with GetX or BLoC. However, it can coexist if required.

In 2025, Riverpod remains one of the top choices for state management in Flutter due to its performance, reliability, and clean architecture. Whether you’re just getting started or looking to scale your project, Riverpod provides the flexibility and safety you need.

By following the example above and integrating it into your real-world applications, you’ll be able to build efficient and maintainable Flutter apps with confidence.

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More