capture method Null safety
- {required BuildContext from,
- required BuildContext? to}
Returns a CapturedThemes object that includes all the InheritedThemes
between the given from
and to
BuildContexts.
The to
context must be an ancestor of the from
context. If to
is
null, all ancestor inherited themes of from
up to the root of the
widget tree are captured.
After calling this method, the themes present between from
and to
are
frozen in the returned CapturedThemes object. If the themes (or their
theme data) change in the original subtree, those changes will not be
applied to the themes captured in the CapturedThemes object - unless
this method is called again to re-capture the updated themes.
To wrap a Widget in the captured themes, call CapturedThemes.wrap.
This method can be expensive if there are many widgets between from
and
to
(it walks the element tree between those nodes).
Implementation
static CapturedThemes capture({ required BuildContext from, required BuildContext? to }) {
assert(from != null);
if (from == to) {
// Nothing to capture.
return CapturedThemes._(const <InheritedTheme>[]);
}
final List<InheritedTheme> themes = <InheritedTheme>[];
final Set<Type> themeTypes = <Type>{};
late bool debugDidFindAncestor;
assert(() {
debugDidFindAncestor = to == null;
return true;
}());
from.visitAncestorElements((Element ancestor) {
if (ancestor == to) {
assert(() {
debugDidFindAncestor = true;
return true;
}());
return false;
}
if (ancestor is InheritedElement && ancestor.widget is InheritedTheme) {
final InheritedTheme theme = ancestor.widget as InheritedTheme;
final Type themeType = theme.runtimeType;
// Only remember the first theme of any type. This assumes
// that inherited themes completely shadow ancestors of the
// same type.
if (!themeTypes.contains(themeType)) {
themeTypes.add(themeType);
themes.add(theme);
}
}
return true;
});
assert(debugDidFindAncestor, 'The provided `to` context must be an ancestor of the `from` context.');
return CapturedThemes._(themes);
}