Last active
May 3, 2026 15:08
-
-
Save rrousselGit/d7acc6b5852421f2a848756ec13b6f17 to your computer and use it in GitHub Desktop.
Experimental Riverpod dartpad
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ignore_for_file: prefer_relative_imports, public_member_api_docs, invalid_use_of_internal_member | |
| import 'package:flutter_riverpod/flutter_riverpod.dart'; | |
| import 'package:flutter_riverpod/misc.dart'; | |
| import 'package:flutter_riverpod/mutation.dart'; | |
| import 'package:flutter/material.dart'; | |
| class Counter extends Notifier<int> { | |
| @override | |
| int build() => 0; | |
| void increment() => state++; | |
| } | |
| void main() { | |
| runApp( | |
| // Adding ProviderScope enables Riverpod for the entire project | |
| const ProviderScope(child: MyApp()), | |
| ); | |
| } | |
| class MyApp extends StatelessWidget { | |
| const MyApp({super.key}); | |
| @override | |
| Widget build(BuildContext context) => MaterialApp(home: Home()); | |
| } | |
| class Home extends ConsumerWidget { | |
| @override | |
| Widget build(BuildContext context, WidgetRef ref) { | |
| return Scaffold( | |
| appBar: AppBar(title: const Text('Counter example')), | |
| body: Center(child: Text('${Counter.new.watch(ref)}')), | |
| floatingActionButton: FloatingActionButton( | |
| // The read method is a utility to read a provider without listening to it | |
| onPressed: () => ref.read(Counter.new.notifier).increment(), | |
| child: const Icon(Icons.add), | |
| ), | |
| ); | |
| } | |
| } | |
| /* Source for the experiment */ | |
| final _fam = Family( | |
| name: null, | |
| dependencies: null, | |
| $allTransitiveDependencies: null, | |
| isAutoDispose: true, | |
| retry: null, | |
| ); | |
| T _watch<T>(MutationTarget target, ProviderBase<T> provider) { | |
| switch (target) { | |
| case Ref(): | |
| return target.watch(provider); | |
| case WidgetRef(): | |
| return target.watch(provider); | |
| case ProviderContainer(): | |
| throw UnsupportedError( | |
| 'Watching a provider from a ProviderContainer is not supported.', | |
| ); | |
| case _: | |
| throw UnsupportedError( | |
| 'Watching a provider from a ${target.runtimeType} is not supported.', | |
| ); | |
| } | |
| } | |
| void _listen<T>( | |
| MutationTarget target, | |
| ProviderBase<T> provider, | |
| void Function(T? previous, T next) listener, | |
| ) { | |
| switch (target) { | |
| case Ref(): | |
| target.listen(provider, listener); | |
| case WidgetRef(): | |
| target.listen(provider, listener); | |
| case ProviderContainer(): | |
| target.listen(provider, listener); | |
| case _: | |
| throw UnsupportedError( | |
| 'Listening to a provider from a ${target.runtimeType} is not supported.', | |
| ); | |
| } | |
| } | |
| T _read<T>(MutationTarget target, ProviderBase<T> provider) { | |
| switch (target) { | |
| case Ref(): | |
| return target.read(provider); | |
| case WidgetRef(): | |
| return target.read(provider); | |
| case ProviderContainer(): | |
| return target.read(provider); | |
| case _: | |
| throw UnsupportedError( | |
| 'Reading a provider from a ${target.runtimeType} is not supported.', | |
| ); | |
| } | |
| } | |
| extension FunctionalProvider<T> on T Function(Ref ref) { | |
| Provider<T> get provider => Provider<T>.internal( | |
| this, | |
| from: _fam, | |
| argument: (this,), | |
| name: null, | |
| dependencies: null, | |
| $allTransitiveDependencies: null, | |
| isAutoDispose: true, | |
| retry: null, | |
| ); | |
| T watch(MutationTarget target) => _watch(target, provider); | |
| void listen( | |
| MutationTarget target, | |
| void Function(T? previous, T next) listener, | |
| ) => _listen(target, provider, listener); | |
| T read(MutationTarget target) => _read(target, provider); | |
| } | |
| extension FunctionalFamily<T, Arg> on T Function(Ref ref, Arg arg) { | |
| Provider<T> provider(Arg arg) => Provider<T>.internal( | |
| (ref) => this(ref, arg), | |
| from: _fam, | |
| argument: (this, arg), | |
| name: null, | |
| dependencies: null, | |
| $allTransitiveDependencies: null, | |
| isAutoDispose: true, | |
| retry: null, | |
| ); | |
| T watch(MutationTarget target, Arg arg) => _watch(target, provider(arg)); | |
| void listen( | |
| MutationTarget target, | |
| Arg arg, | |
| void Function(T? previous, T next) listener, | |
| ) => _listen(target, provider(arg), listener); | |
| T read(MutationTarget target, Arg arg) => _read(target, provider(arg)); | |
| } | |
| extension FunctionalFutureProvider<T> on Future<T> Function(Ref ref) { | |
| FutureProvider<T> get provider => FutureProvider<T>.internal( | |
| this, | |
| from: _fam, | |
| argument: (this,), | |
| name: null, | |
| dependencies: null, | |
| $allTransitiveDependencies: null, | |
| isAutoDispose: true, | |
| retry: null, | |
| ); | |
| AsyncValue<T> watch(MutationTarget target) => _watch(target, provider); | |
| void listen( | |
| MutationTarget target, | |
| void Function(AsyncValue<T>? previous, AsyncValue<T> next) listener, | |
| ) => _listen(target, provider, listener); | |
| AsyncValue<T> read(MutationTarget target) => _read(target, provider); | |
| } | |
| extension FunctionalFutureFamily<T, Arg> on T Function(Ref ref, Arg arg) { | |
| FutureProvider<T> provider(Arg arg) => FutureProvider<T>.internal( | |
| (ref) => this(ref, arg), | |
| from: _fam, | |
| argument: (this, arg), | |
| name: null, | |
| dependencies: null, | |
| $allTransitiveDependencies: null, | |
| isAutoDispose: true, | |
| retry: null, | |
| ); | |
| AsyncValue<T> watch(MutationTarget target, Arg arg) => | |
| _watch(target, provider(arg)); | |
| void listen( | |
| MutationTarget target, | |
| Arg arg, | |
| void Function(AsyncValue<T>? previous, AsyncValue<T> next) listener, | |
| ) => _listen(target, provider(arg), listener); | |
| AsyncValue<T> read(MutationTarget target, Arg arg) => | |
| _read(target, provider(arg)); | |
| } | |
| extension ClassBasedProvider<NotifierT extends Notifier<StateT>, StateT> | |
| on NotifierT Function() { | |
| NotifierProvider<NotifierT, StateT> get provider => | |
| NotifierProvider<NotifierT, StateT>.internal( | |
| this, | |
| from: _fam, | |
| argument: (this,), | |
| name: null, | |
| dependencies: null, | |
| $allTransitiveDependencies: null, | |
| isAutoDispose: true, | |
| retry: null, | |
| ); | |
| ProviderListenable<NotifierT> get notifier => provider.notifier; | |
| StateT watch(MutationTarget target) => _watch(target, provider); | |
| void listen( | |
| MutationTarget target, | |
| void Function(StateT? previous, StateT next) listener, | |
| ) => _listen(target, provider, listener); | |
| StateT read(MutationTarget target) => _read(target, provider); | |
| } | |
| extension ClassBasedFamily<NotifierT extends Notifier<StateT>, StateT, ArgT> | |
| on NotifierT Function(ArgT arg) { | |
| NotifierProvider<NotifierT, StateT> provider(ArgT arg) => | |
| NotifierProvider<NotifierT, StateT>.internal( | |
| () => this(arg), | |
| from: _fam, | |
| argument: (this, arg), | |
| name: null, | |
| dependencies: null, | |
| $allTransitiveDependencies: null, | |
| isAutoDispose: true, | |
| retry: null, | |
| ); | |
| ProviderListenable<NotifierT> notifier(ArgT arg) => provider(arg).notifier; | |
| StateT watch(MutationTarget target, ArgT arg) => _watch(target, provider(arg)); | |
| void listen( | |
| MutationTarget target, | |
| ArgT arg, | |
| void Function(StateT? previous, StateT next) listener, | |
| ) => _listen(target, provider(arg), listener); | |
| StateT read(MutationTarget target, ArgT arg) => _read(target, provider(arg)); | |
| } | |
| extension ClassBasedFutureProvider<NotifierT extends AsyncNotifier<StateT>, StateT> | |
| on NotifierT Function() { | |
| AsyncNotifierProvider<NotifierT, StateT> get provider => | |
| AsyncNotifierProvider<NotifierT, StateT>.internal( | |
| this, | |
| from: _fam, | |
| argument: (this,), | |
| name: null, | |
| dependencies: null, | |
| $allTransitiveDependencies: null, | |
| isAutoDispose: true, | |
| retry: null, | |
| ); | |
| ProviderListenable<NotifierT> get notifier => provider.notifier; | |
| AsyncValue<StateT> watch(MutationTarget target) => _watch(target, provider); | |
| void listen( | |
| MutationTarget target, | |
| void Function(AsyncValue<StateT>? previous, AsyncValue<StateT> next) listener, | |
| ) => _listen(target, provider, listener); | |
| AsyncValue<StateT> read(MutationTarget target) => _read(target, provider); | |
| } | |
| extension ClassBasedFutureFamily<NotifierT extends AsyncNotifier<StateT>, StateT, ArgT> | |
| on NotifierT Function(ArgT arg) { | |
| AsyncNotifierProvider<NotifierT, StateT> provider(ArgT arg) => | |
| AsyncNotifierProvider<NotifierT, StateT>.internal( | |
| () => this(arg), | |
| from: _fam, | |
| argument: (this, arg), | |
| name: null, | |
| dependencies: null, | |
| $allTransitiveDependencies: null, | |
| isAutoDispose: true, | |
| retry: null, | |
| ); | |
| ProviderListenable<NotifierT> notifier(ArgT arg) => provider(arg).notifier; | |
| AsyncValue<StateT> watch(MutationTarget target, ArgT arg) => _watch(target, provider(arg)); | |
| void listen( | |
| MutationTarget target, | |
| ArgT arg, | |
| void Function(AsyncValue<StateT>? previous, AsyncValue<StateT> next) listener, | |
| ) => _listen(target, provider(arg), listener); | |
| AsyncValue<StateT> read(MutationTarget target, ArgT arg) => _read(target, provider(arg)); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment