State Stream Riverpod

An extension library for integrating the state_stream package with Riverpod.

Features

  • Complete Riverpod Integration - Use StateStream as Riverpod Provider
  • Automatic Resource Management - Support for automatic Provider disposal
  • Type-safe State Management - Utilize StateStream's type safety with Riverpod
  • Reactive UI Updates - Automatically reflect StateStream state changes to Widgets

Installation

dependencies:
  state_stream: ^1.0.0
  state_stream_riverpod: ^2.0.0
  flutter_riverpod: ^2.6.1

Basic Usage

Using StateStream as Riverpod Provider

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

// Define Provider that provides StateStream
final counterStreamProvider = Provider.autoDispose<MutableStateStream<int>>((ref) {
  final counter = MutableStateStream<int>(0);

  // Dispose StateStream when Provider is disposed
  ref.onDispose(() {
    counter.close();
  });

  return counter;
});

// Define Provider that gets StateStream state
final counterProvider = StateStreamProvider.autoDispose.state<int>(
  counterStreamProvider,
);

// Use state in Widget
class CounterWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);

    return Column(
      children: [
        Text('Count: $count'),
        ElevatedButton(
          onPressed: () async {
            final counterStream = ref.read(counterStreamProvider);
            await counterStream.updateWithLock((state, emitter) async {
              await emitter.emit(state + 1);
              return null;
            });
          },
          child: Text('Increment'),
        ),
      ],
    );
  }
}

Complex State Management Example

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:state_stream/state_stream.dart';
import 'package:state_stream_riverpod/state_stream_riverpod.dart';

// StateStream managing complex state
class TodoState {
  final List<Todo> todos;
  final bool isLoading;

  const TodoState({
    required this.todos,
    required this.isLoading,
  });

  TodoState copyWith({
    List<Todo>? todos,
    bool? isLoading,
  }) {
    return TodoState(
      todos: todos ?? this.todos,
      isLoading: isLoading ?? this.isLoading,
    );
  }
}

class Todo {
  final String id;
  final String title;
  final bool completed;

  const Todo({
    required this.id,
    required this.title,
    required this.completed,
  });
}

// Provider managing TodoState
final todoStreamProvider = Provider.autoDispose<MutableStateStream<TodoState>>((ref) {
  final todoStream = MutableStateStream<TodoState>(
    TodoState(todos: [], isLoading: false),
  );

  ref.onDispose(() {
    todoStream.close();
  });

  return todoStream;
});

// Provider for getting TodoState
final todoProvider = StateStreamProvider.autoDispose.state<TodoState>(
  todoStreamProvider,
);

// Widget displaying TodoList
class TodoListWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final todoState = ref.watch(todoProvider);

    if (todoState.isLoading) {
      return CircularProgressIndicator();
    }

    return ListView.builder(
      itemCount: todoState.todos.length,
      itemBuilder: (context, index) {
        final todo = todoState.todos[index];
        return ListTile(
          title: Text(todo.title),
          trailing: Checkbox(
            value: todo.completed,
            onChanged: (value) async {
              final todoStream = ref.read(todoStreamProvider);
              await todoStream.updateWithLock((state, emitter) async {
                final updatedTodos = state.todos.map((t) {
                  if (t.id == todo.id) {
                    return Todo(
                      id: t.id,
                      title: t.title,
                      completed: value ?? false,
                    );
                  }
                  return t;
                }).toList();

                await emitter.emit(state.copyWith(todos: updatedTodos));
                return null;
              });
            },
          ),
        );
      },
    );
  }
}

Combination with Asynchronous Processing

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:state_stream/state_stream.dart';
import 'package:state_stream_riverpod/state_stream_riverpod.dart';

// StateStream that fetches data asynchronously
final userStreamProvider = Provider.autoDispose<MutableStateStream<User?>>((ref) {
  final userStream = MutableStateStream<User?>(null);

  // Fetch data on initialization
  _loadUser(userStream);

  ref.onDispose(() {
    userStream.close();
  });

  return userStream;
});

Future<void> _loadUser(MutableStateStream<User?> stream) async {
  await stream.updateWithLock((state, emitter) async {
    // Loading state representation (using separate state class)
    final user = await _fetchUserFromAPI();
    await emitter.emit(user);
    return null;
  });
}

final userProvider = StateStreamProvider.autoDispose.state<User?>(
  userStreamProvider,
);

class UserProfileWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final user = ref.watch(userProvider);

    if (user == null) {
      return CircularProgressIndicator();
    }

    return Card(
      child: Column(
        children: [
          Text('Name: ${user.name}'),
          Text('Email: ${user.email}'),
        ],
      ),
    );
  }
}

API Reference

StateStreamProvider

Utility class for using StateStream as Riverpod Provider.

StateStreamProvider.autoDispose

Provides automatic resource management using NotifierProvider.autoDispose().

NotifierProvider<Notifier<T>, T> state<T>(
  Provider<StateStream<T>> stateStreamProvider,
)
  • stateStreamProvider: Provider that provides StateStream
  • Return value: Provider that provides the current state of StateStream

About Basic State Management

This package only provides Riverpod integration functionality. For basic state management features, please refer to the state_stream package.

License

MIT License