LocalPottery constructor
- Key? key,
- required PotOverrides pots,
- required WidgetBuilder builder,
- void disposer()?,
Creates a LocalPottery widget that associates existing pots with new values and makes them accessible from descendants in the tree via the pots.
This widget defines new factories for existing pots and binds the objects created by them to the pots so that those objects are made available to descendants.
An important fact is that the factories of the existing pots are
not actually replaced, therefore calling the Pot.call method
still returns the object held in the global pot. Use NearestPotOf.of
instead to obtain the local object from the nearest LocalPottery
ancestor. The example below illustrates the behaviour.
final fooPot = Pot(() => Foo(111));
...
class ParentWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return LocalPottery(
pots: {
fooPot: () => Foo(222),
},
builder: (context) {
print(fooPot()); // 111
print(fooPot.of(context)); // 222
return ChildWidget();
},
);
}
}
class ChildWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
print(fooPot()); // 111
print(fooPot.of(context)); // 222
...
}
}
This is useful when you need in descendants some objects that are different from the ones held in global pots but of the same type.
In the following example, a LocalPottery
provides its descendant
(TodoListPage) with a notifier for a specific category. It allows
the previous page to control which category the next page is
associated with.
Navigator.of(context).push(
TodoListPage.route(category: Category.housework),
);
...
class TodoListPage extends StatelessWidget {
const TodoListPage._();
static Route<void> route({required Category category}) {
return MaterialPageRoute(
builder: (context) => LocalPottery(
pots: {
todosNotifierPot: () => TodosNotifierPot(category: category),
},
builder: (context) => const TodoListPage(),
),
);
}
@override
Widget build(BuildContext context) {
// This is a notifier for a list of a specific category.
final notifier = todosNotifierPot.of(context);
return ValueListenableBuilder(
valueListenable: notifier,
builder: (context, state, child) {
return Scaffold(
appBar: AppBar(
// The title is "Housework" if the current
// notifier is for the category of housework.
title: Text(state.category.label),
),
...
);
},
);
}
}
Note that there are several important differences between
LocalPottery
and Pottery:
LocalPottery
creates an object immediately, whereasPottery
creates (replaces, more precisely) an object only if the relevant Pot already have one.- As already mentioned, objects created by
LocalPottery
are only accessible with NearestPotOf.of. - Objects created by
LocalPottery
are not automatically discarded when theLocalPottery
is removed from the tree. Use disposer to do clean-up.
Also note that an error arises only at runtime if the map contains wrong pairs of pot and factory. Make sure to specify a correct factory creating an object of the correct type.
It is advised that LocalPottery
be used only where it is
absolutely necessary. Using it too much may make it harder to
follow the code of your app.
Implementation
const LocalPottery({
super.key,
required this.pots,
required this.builder,
this.disposer,
});