In Riverpod, there isn’t a direct equivalent to BlocListener from the flutter_bloc
package. However, you can achieve the same functionality using a combination of Consumer
or ConsumerWidget
and ref.listen
.
If you need getting started – go to https://programtom.com/dev/2024/09/10/getting-started-guide-of-flutter-riverpod/
Here’s how to replicate the behavior of BlocListener
in flutter_riverpod
:
1. Using ref.listen
in ConsumerWidget
You can use ref.listen
to watch for changes in the state of a provider and trigger side effects like navigation, showing dialogs, or snack bars (similar to BlocListener
).
ref.listen
listens to the provider but doesn’t rebuild the UI when the state changes. It’s perfect for side effects.
Example
Here’s how you can use ref.listen
in a ConsumerWidget
to listen for state changes and perform side effects like navigation, which would be equivalent to what BlocListener
does.
1. State Management (StateNotifier
and State
)
We define the state and logic for handling network requests using StateNotifier
.
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;
class NetworkState {
final bool isLoading;
final bool success;
NetworkState({this.isLoading = false, this.success = false});
}
class NetworkNotifier extends StateNotifier<NetworkState> {
NetworkNotifier() : super(NetworkState());
Future<void> fetchData() async {
state = NetworkState(isLoading: true, success: false);
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));
if (response.statusCode == 200) {
state = NetworkState(isLoading: false, success: true);
} else {
state = NetworkState(isLoading: false, success: false);
}
}
}
final networkProvider = StateNotifierProvider<NetworkNotifier, NetworkState>((ref) {
return NetworkNotifier();
});
2. Using ref.listen
in FirstScreen
(equivalent to BlocListener
)
Now, in your FirstScreen
, you can use ref.listen
to listen for changes in NetworkState
and trigger navigation or any other side effect when the state changes.
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'network_provider.dart'; // Import your provider here
class FirstScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// Listening for changes in NetworkState to trigger side effects
ref.listen<NetworkState>(networkProvider, (previous, next) {
if (next.success) {
// Navigate to second screen when success is true
GoRouter.of(context).go('/second');
}
if (!next.success && previous?.success == false && !next.isLoading) {
// Show error message if network call failed
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Network call failed!')),
);
}
});
// Get the current state
final networkState = ref.watch(networkProvider);
return Scaffold(
appBar: AppBar(title: Text('First Screen')),
body: Center(
child: networkState.isLoading
? CircularProgressIndicator()
: ElevatedButton(
onPressed: () {
// Trigger the network call
ref.read(networkProvider.notifier).fetchData();
},
child: Text('Make Network Call'),
),
),
);
}
}
Key Points:
ref.listen
: This method listens for state changes but doesn’t rebuild the widget. It’s used to trigger side effects like navigation or showing snack bars, making it equivalent toBlocListener
influtter_bloc
.- State Management:
StateNotifier
holds the logic and state for network calls (NetworkNotifier
).- The
NetworkState
contains flags forisLoading
andsuccess
.
- Side Effects in
ref.listen
:- If the network call is successful (
success
istrue
), it navigates to the second screen. How to define the routes in your app, you could check out here: https://programtom.com/dev/2024/09/09/minimal-code-of-flutter-app-using-provider-state-management/ - If the network call fails, it shows an error message using a
SnackBar
.
- If the network call is successful (
Comparison to BlocListener
:
BlocListener
listens for specific changes inbloc
state and triggers side effects without rebuilding the UI.ref.listen
in Riverpod works similarly by listening to changes in the provider’s state and performing side effects without rebuilding the UI.
This approach is simple and clean, allowing you to manage side effects without needing to manually manage widget rebuilds.