📢 Beta Documentation – This documentation and plugin are under active development. The plugin is live and ready to explore, but docs are in beta. Final release coming in May 2026. Please explore, test, and share feedback!

StreamProvider

StreamProvider seamlessly integrates Dart Streams into your Flutter applications.

StreamProvider is ideal for data that produces values over time. It wraps the underlying Stream in an AsyncValue, allowing you to gracefully handle loading and error states without using StreamBuilder.

When to Use StreamProvider

  • Listening to WebSocket events or Server-Sent Events (SSE)
  • Real-time database updates like Firebase Firestore or Supabase
  • Location updates or sensor data

Basic Syntax

Simply return a Stream from a function annotated with @riverpod:

import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'location.g.dart';

@riverpod
Stream<Location> userLocation(UserLocationRef ref) async* {
  final service = ref.watch(locationServiceProvider);
  yield* service.getLocationStream();
}

Using StreamProvider in Widgets

StreamProvider yields an AsyncValue just like FutureProvider, so you can use.when() to render different UI states:

class LocationTracker extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final locationAsync = ref.watch(userLocationProvider);
    
    return locationAsync.when(
      data: (location) => Text('Lat: ${location.lat}, Lng: ${location.lng}'),
      loading: () => CircularProgressIndicator(),
      error: (error, stack) => Text('Error getting location: $error'),
    );
  }
}

Converting Streams to Futures

You can listen to the latest state synchronously or get the next emitted event by appending .future:

ElevatedButton(
  onPressed: () async {
    // Wait for the next location emitted by the stream
    final nextLocation = await ref.read(userLocationProvider.future);
    print(nextLocation);
  },
  child: Text('Get current location'),
)