dependOnInheritedWidgetOfExactType<T extends InheritedWidget> static method

T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>(
  1. BuildContext context, {
  2. Object? aspect,
})

Obtains the nearest widget of the given type T within the current LookupBoundary of context, which must be the type of a concrete InheritedWidget subclass, and registers the provided build context with that widget such that when that widget changes (or a new widget of that type is introduced, or the widget goes away), the build context is rebuilt so that it can obtain new values from that widget.

This method behaves exactly like BuildContext.dependOnInheritedWidgetOfExactType, except it only considers InheritedWidgets of the specified type T between the provided BuildContext and its closest LookupBoundary ancestor. InheritedWidgets past that LookupBoundary are invisible to this method. The root of the tree is treated as an implicit lookup boundary.

This is typically called implicitly from of() static methods, e.g. Theme.of.

This method should not be called from widget constructors or from State.initState methods. While calling this method effectively registers the BuildContext as a dependent for future rebuilds, the constructor and State.initState are lifecycle-locked and only execute once during the initial creation of the element.

If an inherited value changes later, the framework will correctly trigger the State.build method to run again, but it cannot re-run the constructor or State.initState. Consequently, if any internal variables, controllers, or side effects were initialized using a "snapshot" of the inherited value in those one-time methods, they will retain their original, now-obsolete values. This leads to a state desynchronization where the widget's State.build method might be using updated data while its internal logic remains bound to stale data captured during State.initState.

To ensure the widget stays in sync, call this (directly or indirectly) from build methods, layout and paint callbacks, or from State.didChangeDependencies.

State.didChangeDependencies is called immediately after State.initState and is re-invoked whenever the inherited widget this context depends on changes, until the next time the widget or one of its ancestors is moved (for example, because an ancestor is added or removed). This allows the State to update internal variables or perform initialization logic that depends on the inherited value before State.build is called.

This method should not be called from State.dispose because the element tree is no longer stable at that time. To refer to an ancestor from that method, save a reference to the ancestor in State.didChangeDependencies. It is safe to use this method from State.deactivate, which is called whenever the widget is removed from the tree.

It is also possible to call this method from interaction event handlers (e.g. gesture callbacks) or timers, to obtain a value once, as long as that value is not cached and/or reused later.

Calling this method is O(1) with a small constant factor, but will lead to the widget being rebuilt more often.

The aspect parameter is only used when T is an InheritedWidget subclasses that supports partial updates, like InheritedModel. It specifies what "aspect" of the inherited widget this context depends on.

Implementation

static T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>(
  BuildContext context, {
  Object? aspect,
}) {
  // The following call makes sure that context depends on something so
  // Element.didChangeDependencies is called when context moves in the tree
  // even when requested dependency remains unfulfilled (i.e. null is
  // returned).
  context.dependOnInheritedWidgetOfExactType<LookupBoundary>();
  final InheritedElement? candidate = getElementForInheritedWidgetOfExactType<T>(context);
  if (candidate == null) {
    return null;
  }
  context.dependOnInheritedElement(candidate, aspect: aspect);
  return candidate.widget as T;
}