0 purchases
bilocator
bilocator #
A Flutter hybrid locator that manages models in a global registry (like GetIt) and in the widget tree (like Provider, InheritedWidget).
Bilocator is used my by the state management packages, so is battle tested.
Bilocator goals:
Locate single services in a global registry.
Locate inherited models in the widget tree.
Bind the lifecycle of both single services and inherited models to widgets.
Support lazy loading.
Support models being simultaneously locatable in the registry and on the widget tree.
Work alone or with other state management packages (RxDart, Provider, GetIt, ...).
Be scalable and performant, so suitable for both indy and production apps.
Bilocator can be used as a standalone locator or integrated into state management libraries. mvvm+ uses Bilocator.
Single Services #
Single services are those single instances that need to located from anywhere in the widget tree.
To add a single service to the registry, give a builder to a Bilocator widget and add it to the widget tree:
Bilocator<MyService>(
builder: () => MyService(),
child: MyWidget(),
);
copied to clipboard
Inherited Models #
Inherited models are located on the widget tree (similar to Provider, InheritedWidget). Unlike single services, you can add as many inherited models of the same type as you need.
By default, models are stored in the registry (location: Location.registry). To add models to the widget tree, set location to Location.tree:
Bilocator<MyModel>(
builder: () => MyModel(),
location: Location.tree,
child: MyWidget(),
);
copied to clipboard
Bilocator widgets unregister their services and models when they are removed from the widget tree. If their services and models are ChangeNotifiers, the Bilocator widgets optionally call the ChangeNotifiers' dispose method.
How to Locate Single Services #
The single service instance can located from anywhere by type:
final myService = Bilocator.get<MyService>();
copied to clipboard
If more than one instance of a service of the same type is needed, you can specify a unique name:
Bilocator<MyService>(
builder: () => MyService(),
name: 'some unique name',
child: MyWidget(),
);
copied to clipboard
And then get the service by type and name:
final myService = Bilocator.get<MyService>(name: 'some unique name');
copied to clipboard
When you want to manage multiple services with a single widget, use Bilocators:
Bilocators(
delegates: [
BilocatorDelegate<MyService>(builder: () => MyService()),
BilocatorDelegate<MyOtherService>(builder: () => MyOtherService()),
],
child: MyWidget(),
);
copied to clipboard
For rare use cases where you need to directly manage registering and unregistering services (instead of letting Bilocator and Bilocators manage your services), you can use the static register and unregister functions:
Bilocator.register<MyService>(builder: () => MyService())
copied to clipboard
Locating Inherited Models #
Bilocator implements the observer pattern as a mixin that can my added to your models and widgets.
class MyModel with Observer {
int counter;
}
copied to clipboard
Models and widgets that use Observer can listenTo inherited models and single services. To listen to single services:
final text = listenTo<MyWidgetViewModel>(listener: myListener).text;
copied to clipboard
To listen to inherited models on the widget tree, add the context parameter:
final text = listenTo<MyWidgetViewModel>(context: context, listener: myListener).text;
copied to clipboard
For convenience, Observer also adds a get function that doesn't required the preceding Bilocator class name. Models and widgets that use Observer can get single services:
final text = get<MyModel>().text;
copied to clipboard
And get inherited models:
final text = get<MyModel>(context: context).text;
copied to clipboard
.of #
The of function (Theme.of, Provider.of) is known to introduce unnecessary dependencies in apps (and consequently unnecessary builds). So, using listenTo is recommended. However, if you are migrating from another library that uses of (or simply like using of), Bilocator includes of in its BuildContext extension:
final text = context.of<MyModel>().text;
copied to clipboard
Or, you get use the BuildContext extension to get models without adding a dependency:
final text = context.get<MyModel>().text;
copied to clipboard
Registering an Inherited Model as a Single Service #
To make an inherited model on the widget tree visible to widgets on other branches, register the inherited model as a single service:
register<MyModel>(context);
copied to clipboard
After registering, the model will be available from anywhere. When no longer needed in the registry, simply unregister it:
unregister<MyModel>(context);
copied to clipboard
Some Trivia #
In the non-technical world, religious zealots and mystics that claim to have the power of locating in two places at once are referred to as bilocators.
Example #
(The source code for this example is under the Pub.dev "Example" tab and in the GitHub example/lib/main.dart file.)
There are three registered services:
ColorNotifier changes its color every N seconds and then calls notifyListeners.
FortyTwoService holds a number that is equal to 42.
RandomService generates a random number.
The first service was added to the widget tree with Bilocator. The remaining services were added with Bilocators.
That's It! #
If you have questions or suggestions on anything Bilocator, please do not hesitate to contact me.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.