flutter_it library
A convenience package that re-exports the entire flutter_it ecosystem.
This package provides a single import for all flutter_it packages:
- get_it: Service locator and dependency injection
- watch_it: Reactive state management built on get_it
- command_it: Command pattern with automatic loading/error states
- listen_it: ValueListenable operators and reactive collections
Instead of importing each package separately:
import 'package:get_it/get_it.dart';
import 'package:watch_it/watch_it.dart';
import 'package:command_it/command_it.dart';
import 'package:listen_it/listen_it.dart';
You can now just import:
import 'package:flutter_it/flutter_it.dart';
Learn more at https://flutter-it.dev
Classes
-
Command<
TParam, TResult> -
Command capsules a given handler function that can then be run by its run method.
The result of this method is then published through its
ValueListenableinterface Additionally it offers otherValueListenablesfor it's current execution state, if the command can be run and for all possibly thrown exceptions during command execution. -
CommandAsync<
TParam, TResult> -
CommandBuilder<
TParam, TResult> -
CommandError<
TParam> -
CommandError wraps an occurring error together with the argument that was
passed when the command was called.
This sort of objects are emitted on the
.errorsValueListenable of the Command -
CommandResult<
TParam, TResult> -
Combined execution state of a
Commandrepresented using four of its fields. A CommandResult will be issued for any state change of any of its fields During normal command execution you will get this items by listening at the command's.resultsValueListenable. -
CommandSync<
TParam, TResult> - CustomChangeNotifier
-
CustomValueNotifier<
T> -
Sometimes you want a ValueNotifier where you can control when its
listeners are notified. With the
CustomValueNotifieryou can do this: If you pass CustomNotifierMode.always for the mode parameter,notifierListenerswill be called everytime you assign a value to the value property independent of if the value is different from the previous one. If you pass CustomNotifierMode.manual for the mode parameter,notifierListenerswill not be called when you assign a value to the value property. You have to call it manually to notify the Listeners. Aditionally it has a listenerCount property that tells you how many listeners are currently listening to the notifier. - Disposable
- If objects that are registered inside GetIt implements Disposable the onDispose method will be called whenever that Object is unregistered, reset or its enclosing Scope is popped
- ErrorFilerConstant
- ErrorFilter
-
Instead of the current parameter
catchAlwayscommands can get an optional parametererrorFilterof type ErrorFilter which can be used to customize the error handling. Additionally there will be a Global error Filter that is used if no local error filter is present. -
ErrorFilterExcemption<
T> - GetIt
- Very simple and easy to use service locator You register your object creation factory or an instance of an object with registerFactory, registerSingleton or registerLazySingleton And retrieve the desired object using get or call your locator as function as its a callable class Additionally GetIt offers asynchronous creation functions as well as functions to synchronize the async initialization of multiple Singletons
- GlobalErrorFilter
- Error filter that routes errors only to the global handler. Use this when you want all errors to go to the global handler, regardless of whether there are local listeners.
- GlobalIfNoLocalErrorFilter
- Error filter that routes errors to global handler if no local handler is present. This is the default error filter for all commands.
- InitDependency
- Data structure used to identify a dependency by type and instanceName
- ListenableSubscription
-
Object that is returned by
listenthat allows you to stop the calling of the handler that you passed to it. -
ListNotifier<
T> -
A List that behaves like
ValueNotifierif its data changes. - LocalAndGlobalErrorFilter
- Error filter that routes errors to both local and global handlers.
- LocalErrorFilter
- Error filter that routes errors only to local handlers (.errors or .results listeners).
-
MapNotifier<
K, V> -
A Map that behaves like
ValueNotifierif its data changes. -
MockCommand<
TParam, TResult> -
MockCommandallows you to easily mock an Command for your Unit and UI tests Mocking a command withmockitohttps://pub.flutter-io.cn/packages/mockito has its limitations. -
ObjectRegistration<
T extends Object> - PredicatesErrorFilter
- Takes a list of predicate functions and returns the first non null ErrorReaction or ErrorReaction.defaulErrorFilter if no predicate matches. The predicates are called in the order of the list. which means if you want to match against a type hierarchy you have to put the more specific type first. You can define your own predicates or use the errorFilter function like this
- ProgressHandle
- Provides bidirectional communication for commands with progress tracking, status messages, and cooperative cancellation.
-
SetNotifier<
T> -
A Set that behaves like
ValueNotifierif its data changes. - ShadowChangeHandlers
-
If an object implements the
ShadowChangeHandlerif will get notified if an Object with the same registration type and name is registered on a higher scope which will shadow it. It also will get notified if the shadowing object is removed from GetIt - TableErrorFilter
- This filter allows to pass a table of error types and the corresponding ErrorReactions. Attention, the table can only compare the runtime type of the error on equality, not the type hierarchy. Normally you couldn't match against the Excpeption type, because the runtime type of an exception is always _Exception which is a private type. As Exception is such a basic error type this funcion has a workaround for this case. I recommend to use the PredicatesErrorFilter instead unless you have a very specific use case that requires to compare for type equality.
-
UndoableCommand<
TParam, TResult, TUndoState> -
UndoStack<
E> - WatchingStatefulWidget
- WatchingWidget
- WatchItSubTreeTraceControl
- An inherited widget that controls tracing behavior for WatchingWidgets in its subtree.
- WillSignalReady
-
If your singleton that you register wants to use the manually signalling
of its ready state, it can implement this interface class instead of using
the
signalsReadyparameter of the registration functions (you don't really have to implement much ;-) )
Enums
- CustomNotifierMode
- ErrorReaction
- ObjectRegistrationType
-
You will see a rather esoteric looking test
(const Object() is! T)at several places. It tests ifTis a real type and not Object or dynamic. For each registered factory/singleton an ObjectRegistration<T> is created it holds either the instance of a Singleton or/and the creation functions for creating an instance whengetis called - WatchItEvent
- Enum representing different types of events in watch_it
Extensions
-
FunctionaListener
on ValueListenable<
T> -
extension functions on
ValueListenablethat allows you to work with them almost as if it was a synchronous stream. Each extension function returns a newValueNotifierthat updates its value when the value ofthischanges You can chain these functions to build complex processing pipelines from a simpleValueListenableIn the examples we use listen to react on value changes. Instead of applying listen you could also pass the end of the function chain to aValueListenableBuilder - FunctionaListener2 on Listenable
-
ToWidgeCommandResult
on CommandResult<
TParam, TResult> -
ValueListenablePipe
on ValueListenable<
T> - Extension to pipe ValueListenable changes to a Command.
Properties
- di → GetIt
-
WatchIt exports the default instance of get_it as a global variable which lets
you access it from anywhere in your app. To access any get_it registered
object you only have to type
di<MyType>()instead ofGetIt.I<MyType>(). if you don't want to use a different instance of get_it you can pass it to the functions of this library as an optional parameterfinal - enableSubTreeTracing ↔ bool
-
Global switch to enable/disable subtree tracing
getter/setter pair
- sl → GetIt
-
for people taking offense that the name di is not correct because GetIt is
a service locator and not a dependency injection container, we provide an
alias for it.
final
- watchItLogFunction ↔ WatchItLogFunction?
-
Global logging function that can be overridden by users
Default implementation prints to console
getter/setter pair
Functions
-
allReady(
{void onReady(BuildContext context)?, void onError(BuildContext context, Object? error)?, Duration? timeout, bool callHandlerOnlyOnce = false}) → bool -
returns
trueif all registered async or dependent objects are ready and callonReadyandonErrorhandlers when the all-ready state is reached. You can force a timeout Exception if allReady hasn't returnedtruewithintimeout. It will trigger a rebuild if this state changes If noonErroris passed in it will throw an exception if an error occurs while waiting for the all-ready state.callHandlerOnlyOncedetermines if theonReadyandonErrorhandlers should be called only once or on every rebuild after the all-ready state has been reached. -
allReadyHandler(
void onReady(BuildContext context)?, {void onError(BuildContext context, Object? error)?, Duration? timeout, bool callHandlerOnlyOnce = false}) → void -
registers a handler that is called when the all-ready state is reached
it does not trigger a rebuild like allReady does.
You can force a timeout Exception if allReady has completed
within
timeoutwhich will callonErrorif noonErroris passed in it will throw an exception if an error occurs while waiting for the all-ready state.callHandlerOnlyOncedetermines if theonReadyandonErrorhandlers should be called only once or on every rebuild after the all-ready state has been reached. -
callAfterEveryBuild(
void callback(BuildContext context, void cancel())) → void - Executes a callback after every frame has been rendered. This is useful when you need to perform operations after each rebuild that require the widget tree to be fully built and laid out, such as:
-
callOnce(
void init(BuildContext context), {void dispose()?}) → void -
If you want to execute a function only on the first built (even in in a StatelessWidget),
you can use the
callOncefunction anywhere in your build function. It has an optionaldisposehandler which will be called when the widget is disposed. -
callOnceAfterThisBuild(
void callback(BuildContext context)) → void - Executes a callback once after the current build has been rendered. This is useful when you need to perform operations that require the widget tree to be fully built and laid out, such as:
-
createOnce<
T extends Object> (T factoryFunc(), {void dispose(T)?}) → T -
createOnce creates an object with the factory function
factoryFuncat the time of the first build and disposes it when the widget is disposed if the object implements the Disposable interface. on every rebuild the same object is returneddisposeallows you to pass a custom dispose function to dispose of the object. if provided it will override the default dispose behavior. -
createOnceAsync<
T> (Future< T> factoryFunc(), {required T initialValue, void dispose(T)?}) → AsyncSnapshot<T> -
createOnceAsync creates an object with the async factory function
factoryFuncat the time of the first build and disposes it when the widget is disposed if the object implements the Disposable interface.initialValueis the value that will be returned until the factory function completes. When thefactoryFunccompletes the value will be updated with the new value and the widget will be rebuilt.disposeallows you to pass a custom dispose function to dispose of the object. if provided it will override the default dispose behavior. -
enableTracing(
{bool logRebuilds = true, bool logHandlers = true, bool logHelperFunctions = true}) → void -
enable tracing for the current build function has to be called before
any other watch_it functions in the same build function
If both
logRebuildsandlogHandlersare true then both will be logged if you want to enable tracing for the complete subtree you can wrap the widget that you want to trace including its child widgets with WatchItSubTreeTraceControl -
errorFilter<
TError> (Object error, ErrorReaction reaction) → ErrorReaction? -
isReady<
T extends Object> ({void onReady(BuildContext context)?, void onError(BuildContext context, Object? error)?, Duration? timeout, String? instanceName}) → bool -
returns
trueif the registered async or dependent object defined byTandinstanceNameis ready and callsonReadyonErrorhandlers when the ready state is reached. You can force a timeout Exception if isReady hasn't returnedtruewithintimeout. It will trigger a rebuild if this state changes. if noonErroris passed in it will throw an exception if an error occurs -
onDispose(
void dispose()) → void -
To dispose anything when the widget is disposed you can use call
onDisposeanywhere in your build function. -
pushScope(
{void init(GetIt getIt)?, void dispose()?, bool isFinal = false}) → void -
Pushes a new GetIt-Scope. After pushing, it executes
initwhere you can register objects that should only exist as long as this scope exists. Can be called inside thebuildmethod of aStatelessWidget. It ensures that it's only called once in the lifetime of a widget.isFinalallows only objects ininitto be registered so that other components cannot accidentally register to this scope. When the widget is destroyed the scope also gets destroyed afterdisposeis executed. If you use this function and you have registered your objects with an async disposal function, that function won't be awaited. I would recommend doing pushing and popping from your business layer but sometimes this might come in handy. -
rebuildOnScopeChanges(
) → bool? -
Will trigger a rebuild of the Widget if any new GetIt-Scope is pushed or popped.
This function will return
trueif the change was a push otherwisefalse. If no change has happened then the return value will be null. -
registerChangeNotifierHandler<
T extends ChangeNotifier> ({required void handler(BuildContext context, T newValue, void cancel()), T? target, bool executeImmediately = false, String? instanceName, GetIt? getIt}) → void -
registerChangeNotifierHandler registers a
handlerfunction for aChangeNotifierexactly once on the first build and unregisters it when the widget is destroyed. If you setexecuteImmediatelytotruethe handler will be called immediately with the current value of theChangeNotifierand not on the first change notification. All handler functions get passed in acancelfunction that allows to kill the registration from inside the handler. If you want to register a handler to a ChangeNotifier that is not registered in get_it you can pass it astarget.instanceNameis the optional name of the instance if you registered it with a name in get_it. -
registerFutureHandler<
T extends Object, R> ({Future< R> select(T)?, T? target, required void handler(BuildContext context, AsyncSnapshot<R?> newValue, void cancel()), R? initialValue, String? instanceName, bool callHandlerOnlyOnce = false, bool allowFutureChange = false, GetIt? getIt}) → void -
registerFutureHandler registers a
handlerfunction for aFutureexactly once on the first build and unregisters it when the widget is destroyed. This handler will only be called once when theFuturecompletes.selectallows you to register the handler to a member of the of the Object stored in GetIt. If you passinitialValueyour passed handler will be executed immediately with that value. All handlers get passed in acancelfunction that allows to kill the registration from inside the handler. If the Future has completedhandlerwill be called every time until the handler callscancelor the widget is destroyed -
registerHandler<
T extends Object, R> ({ValueListenable< R> select(T)?, required void handler(BuildContext context, R newValue, void cancel()), T? target, bool allowObservableChange = false, bool executeImmediately = false, String? instanceName, GetIt? getIt}) → void -
registerHandler registers a
handlerfunction for aValueListenableexactly once on the first build and unregister it when the widget is destroyed.selectallows you to register the handler to a member of the of the Object stored in GetIt. If you setexecuteImmediatelytotruethe handler will be called immediately with the current value of theValueListenableand not on the first change notification. All handler functions get passed in acancelfunction that allows to kill the registration from inside the handler. If you want to register a handler to a Listenable that is not registered in get_it you can pass it astarget. if you pass null asselect, T ortargethas to be a Listenable or ValueListenable. -
registerStreamHandler<
T extends Object, R> ({Stream< R> select(T)?, required void handler(BuildContext context, AsyncSnapshot<R?> newValue, void cancel()), R? initialValue, bool allowStreamChange = false, T? target, String? instanceName, GetIt? getIt}) → void -
registerStreamHandler registers a
handlerfunction for aStreamexactly once on the first build and unregisters it when the widget is destroyed.selectallows you to register the handler to a member of the of the Object stored in GetIt. If you passinitialValueyour passed handler will be executed immediately with that value All handler functions get passed in acancelfunction that allows to kill the registration from inside the handler. If you want to register a handler to a Stream that is not registered in get_it you can pass it astarget. if you pass null asselect, T ortargethas to be aStream<R>.instanceNameis the optional name of the instance if you registered it with a name in get_it. -
throwIf(
bool condition, Object error) → void - Two handy functions that help me to express my intention clearer and shorter to check for runtime errors
-
throwIfNot(
bool condition, Object error) → void -
watch<
T extends Listenable> (T target) → T - The Watch functions:
-
watchFuture<
T extends Object, R> (Future< R> select(T)?, {T? target, required R initialValue, String? instanceName, bool preserveState = true, bool allowFutureChange = false, GetIt? getIt}) → AsyncSnapshot<R> -
watchFuture observes the
Futurereturned byselectand triggers a rebuild as soon as thisFuturecompletes. After that it returns anAsyncSnapshotwith the received data from theFutureWhen you call watchFuture a second time on the sameFutureit will return the last received data but not observe the Future a another time. To be able to use watchFuture inside abuildfunction we have to passinitialValueso that it can return something before theFuturehas completed ifselectreturns a differentFuturethan on the last call, watchFuture will ignore the completion of the previous Future and observe the completion of the new Future.preserveStatedetermines then if the new initial value should be the last value of the previous Future or againinitialValueIf you want to observe aFuturethat is not registered in get_it you can pass it astarget. if you pass null asselect, T ortargethas to be aFuture<R>.instanceNameis the optional name of the instance if you registered it with a name in get_it. -
watchIt<
T extends Listenable> ({String? instanceName, GetIt? getIt}) → T -
watchIt observes any Listenable registered in get_it and triggers a rebuild whenever
it notifies a change. Its basically a shortcut for
watch(di<T>())instanceNameis the optional name of the instance if you registered it with a name in get_it.getItis the optional instance of get_it to use if you don't want to use the default one. 99% of the time you won't need this. -
watchPropertyValue<
T extends Listenable, R> (R selectProperty(T), {T? target, String? instanceName, GetIt? getIt}) → R -
watchPropertyValue allows you to observe a property of a Listenable object and trigger a rebuild
whenever the Listenable notifies a change and the value of the property changes and
returns the current value of the property.
You can achieve a similar result with
watchIt<UserManager>().userNamebut that would trigger a rebuild whenever any property of the UserManager changes.final userName = watchPropertyValue<UserManager, String>((user) => user.userName);could be an example. Or even more expressive and concise:final userName = watchPropertyValue((UserManager user) => user.userName);which lets tha analyzer infer the type of T and R. -
watchStream<
T extends Object, R> (Stream< R> select(T)?, {T? target, R? initialValue, bool preserveState = true, bool allowStreamChange = false, String? instanceName, GetIt? getIt}) → AsyncSnapshot<R> -
watchStream subscribes to the
Streamreturned byselectand returns anAsyncSnapshotwith the latest received data from theStreamWhenever new data is received it triggers a rebuild. When you call watchStream a second time on the sameStreamit will return the last received data but not subscribe another time. To be able to use watchStream inside abuildfunction we have to passinitialValueso that it can return something before it has received the first data ifselectreturns a different Stream than on the last call, watchStream will cancel the previous subscription and subscribe to the new stream.preserveStatedetermines then if the new initial value should be the last value of the previous stream or againinitialValueIf you want to observe aStreamthat is not registered in get_it you can pass it astarget. if you pass null asselect, T ortargethas to be aStream<R>.instanceNameis the optional name of the instance if you registered it with a name in get_it. -
watchValue<
T extends Object, R> (ValueListenable< R> selectProperty(T), {bool allowObservableChange = false, String? instanceName, GetIt? getIt}) → R -
watchValue observes a ValueListenable property of an object registered in get_it
and triggers a rebuild whenever it notifies a change and returns its current
value. It's basically a shortcut for
watchIt<T>().valueAs this is a common scenario it allows us a type safe concise way to do this.final userName = watchValue<UserManager, String>((user) => user.userName);is an example of how to use it. We can use the strength of generics to infer the type of the property and write it even more expressively like this:final userName = watchValue((UserManager user) => user.userName);
Typedefs
-
DisposingFunc<
T> = FutureOr Function(T param) -
Signature for disposing function
because closures like
(x){}have a return type of Null we don't useFutureOr<void> - ErrorFilterFn = ErrorReaction Function(Object error, StackTrace stackTrace)
- Function-based error filter for simple inline error handling logic.
- ErrorFilterPredicate = ErrorReaction? Function(Object error, StackTrace stackTrace)
-
ExecuteInsteadHandler<
TParam> = RunInsteadHandler< TParam> - Deprecated: Use RunInsteadHandler instead.
-
FactoryFunc<
T> = T Function() - Signature of the factory function used by non async factories
-
FactoryFuncAsync<
T> = Future< T> Function() - Signature of the factory function used by async factories
-
FactoryFuncParam<
T, P1, P2> = T Function(P1 param1, P2 param2) -
For Factories that expect up to two parameters if you need only one use
voidfor the one you don't use -
FactoryFuncParamAsync<
T, P1, P2> = Future< T> Function(P1 param1, P2 param2) -
For async Factories that expect up to two parameters if you need only one use
voidfor the one you don't use -
RunInsteadHandler<
TParam> = void Function(TParam?) - ScopeDisposeFunc = FutureOr Function()
- Signature for disposing function on scope level
-
UndoFn<
TUndoState, TResult> = FutureOr< TResult> Function(UndoStack<TUndoState> undoStack, Object? reason) - Type signature of a function that is called when the last command call should be undone.
- WatchItLogFunction = void Function({required WatchItEvent eventType, Object? lastValue, Object? observedObject, Object? parentObject, String? sourceLocationOfWatch})
- Typedef for the logging function signature
Exceptions / Errors
- UndoException
- In case that an undo of a command fails, this exception wraps the error to distinguish it from other exceptions.
- WaitingTimeOutException