Remember to use InheritedWidget to think

Inheritedwidgets are an essential component of a project that shares user data. The cliche Provider framework is also implemented based on InheritedWidget

Introduction to the

The InheritedWidget component is a functional bureau that shares data from top to bottom. As the child components to BuildContext. DependOnInheritedWidgetOfExactType method to get data from the parent component.

It’s worth mentioning that this top-down approach to providing book-sharing data is the opposite of Notification delivery. The similarity is that both are initiated by child components. InheritedWidget is an InheritedWidget that uses content to look up data up the tree, and Notification is an InheritedWidget that uses content to initiate notifications up.

The characteristics of

  1. Child component pass[BuildContext.dependOnInheritedWidgetOfExactType]Method to find the corresponding nearestInheritedWidgetAnd get the data.
  2. InheritedWidgetTo provide by custom or agreementofStatic method to make it easier for child components to get data. This method does not necessarily return the inherited widget; it can also return other data.
  3. callofMethod components must be in theInheritedWidgetInside. If used in the same widget, you can passBuilderWrap the components you need to use.

role

In use, we find that the InheritedWidget uses the parent component to provide data, and the child component can search the corresponding shared data from the bottom up, which is intuitive.

A common way to update data incorrectly

SetState: We’ve seen a lot of articles online about using inheritedWidgets and updating data. But this just shows what this component does. The vast majority share data with final declarations within the InheritedWidget component. Then the parent component is forced to refresh by setState in the parent component, and the InheritedWidget component is also refreshed. Of course, its multi-layer child components are also rebuilt, causing a lot of unnecessary consumption.

How to optimize?

Inheritedwidgets provide data sharing, avoiding the need for data to be passed through layers of claims from top to bottom. It’s also very clear where we use the data. The next thing to do is to have the specified component update the data after it is refreshed. ValueNotifier comes to mind: When inheritedWidgets share data, they are wrapped with ValueNotifier, and the data types that inheritedWidgets get from the OF method are also ValueNotifier, implemented with ValueListenableBuilder where they are used.

Think further

As mentioned in the InheritedWidget article in the source code Analysis series of Flutter, modify the of method:

  • dependOnInheritedWidgetOfExactType

  • getElementForInheritedWidgetOfExactType().widget

    The difference between the two: Call dependOnInheritedWidgetOfExactType () and getElementForInheritedWidgetOfExactType () difference is that the former will depend on registration, while the latter is not, So the call dependOnInheritedWidgetOfExactType (), InheritedWidget and rely on it and of the sons of component relationship registration is complete, when after InheritedWidget changes, will update depends on its components, That is, the didChangeDependencies() and build() methods that call these descendant components. And when the call is getElementForInheritedWidgetOfExactType (), since there is no registration dependencies, so after when InheritedWidget changes, the children will not update the corresponding Widget.

    @override T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>( {Object? aspect}) { assert(_debugCheckStateIsActiveForAncestorLookup()); final InheritedElement? ancestor = _inheritedWidgets == null ? null : _inheritedWidgets! [T]; If (ancestor! = null) { assert(ancestor is InheritedElement); return dependOnInheritedElement(ancestor, aspect: aspect) as T; } _hadUnsatisfiedDependencies = true; return null; } @override InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>() { assert(_debugCheckStateIsActiveForAncestorLookup()); final InheritedElement? ancestor = _inheritedWidgets == null ? null : _inheritedWidgets! [T]; return ancestor; }Copy the code

Obviously changed to getElementForInheritedWidgetOfExactType < T > () the widget, will need a non less, also is a good thing.

Further reflection leads to doubt

Since ValueNotifier is used to combine the InheritedWidget with the InheritedWidget, when we change the value of ValueNotifier to change the page, the InheritedWidget component is not rebuilt and does not trigger updateShouldNotify. Even in child components that use data, the didChangeDependencies method is not called when value changes. So exactly how the OF method is implemented depends on the business design.

The pictures in the article are borrowed fromSource Code Analysis series InheritedWidget