Review past

The Journey of Flutter from scratch: StatelessWidget

The Journey of Flutter from Scratch: StatefulWidget

In previous articles, you covered the features of StatelessWidgets and StatefulWidgets and how they render.

We’re talking about their other sibling InheritedWidget.

features

InheritedWidget is an important functional component of Flutter that provides data to be passed from top to bottom in the widget tree. Ensure that data is shared among the different child widgets. This works well for scenarios that require shared data. For example, inheritedWidgets are used to share app theme and language information in the Flutter SDK.

In case you’re a little fuzzy, let’s take a look at the InheritedWidget with a simple example.

The sample

Everyone who started learning about Flutter has seen the official counter example. We have transformed the official supplied counter example with an InheritedWidget.

First we need a CountInheritedWidget, which inherits from the InheritedWidget.

class CountInheritedWidget extends InheritedWidget { CountInheritedWidget({@required this.count, Widget child}) : super(child: child); Final int count; // Get the CountInheritedWidget instance uniformly, Static CountInheritedWidget of(BuildContext context) {// We must call static CountInheritedWidget of(BuildContext context) {// Child widgets that call shared data will not be called back to the didChangeDependencies method, that is, child widgets will not update //return context.getElementForInheritedWidgetOfExactType<CountInheritedWidget>().widget;
    returncontext.dependOnInheritedWidgetOfExactType<CountInheritedWidget>(); } / /trueOverride bool updateShouldNotify(CountInheritedWidget oldWidget) {return oldWidget.count != count;
  }
}
Copy the code
  1. Provide the quantity count of the share count in the CountInheritedWidget
  2. It also provides a unified of method for the outside world to get an instance of the CountInheritedWidget
  3. Finally, the updateShouldNotify method is overridden to notify child widgets that depend on the share count to update

Now that you have the provision of the shared data count, it’s time to use it in specific child widgets.

We pull out a CountText child widget

class CountText extends StatefulWidget {
  @override
  _CountTextState createState() {
    return _CountTextState();
  }
}
 
class _CountTextState extends State<CountText> {
  @override
  Widget build(BuildContext context) {
    return Text("count: ${CountInheritedWidget.of(context).count.toString()}");
  }
 
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print("didChangeDependencies"); }}Copy the code
  1. Internally, the shared data count in CountInheritedWidget is referenced, and the instance of CountInheritedWidget is obtained through the of method
  2. DidChangeDependencies can be used to listen for child Widget dependencies that change backwards

Finally, we will combine the CountInheritedWidget with CountText to see the effect through a simple click increment event

class CountWidget extends StatefulWidget {
  @override
  _CountState createState() {
    return _CountState();
  }
}
 
class _CountState extends State<CountWidget> {
  int count = 0;
 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Count App',
      theme: new ThemeData(primarySwatch: Colors.blue),
      home: Scaffold(
        appBar: AppBar(
          title: Text("Count"),
        ),
        body: Center(
          child: CountInheritedWidget(
            count: count,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                CountText(),
                RaisedButton(
                  onPressed: () => setState(() => count++),
                  child: Text("Increment"), a)],),),),),); }}Copy the code

The hierarchy above is that CountText happens to be a child widget of CountInheritedWidget.

Now we change the external count value directly by clicking on the event. If the InheritedWidget’s top-down data transfer is enabled, the count referenced in CountText will be synchronized with the external count, and the application will be incremented. DidChangeDependencies in CountText is also called back when the count of the dependencies changes.

So let’s just run it

Click the output log

I/flutter: didChangeDependencies
Copy the code

Explain InheritedWidget effect has been to take effect, through the use of InheritedWidget, we can easily in the nested data, for the bottom of the child widget to the upper or the entire widget to share data.

Analysis of the

The child Widget’s didChangeDependencies are called back when the dependency changes, but because you might do something special in that method, such as a network request. It just needs to happen once. Using our example above, it would be called repeatedly as count subincrements.

To prevent the call to didChangeDependencies, let’s look again at the commented part of the of method in the CountInheritedWidget

Static CountInheritedWidget of(BuildContext Context) {// Child widgets that call shared data will not call back to the didChangeDependencies method, that is, child widgets will not update //return context.getElementForInheritedWidgetOfExactType<CountInheritedWidget>().widget;
    return context.dependOnInheritedWidgetOfExactType<CountInheritedWidget>();
  }
Copy the code

We are using the dependOnInheritedWidgetOfExactType method, relying on Shared data change back to the tone of the widget when didChangeDependencies method, if we don’t want to YaoZi widget call this method, Can use the annotation code, through getElementForInheritedWidgetOfExactType method to get the share data.

If we run the project again at this point and click Count increment, the console will no longer log. This resolves repeated calls to didChangeDependencies.

And is the main difference between these two methods in the process of dependOnInheritedWidgetOfExactType calls will register dependencies

@override InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object aspect }) { assert(ancestor ! = null); _dependencies ?? = HashSet<InheritedElement>(); _dependencies.add(ancestor); ancestor.updateDependencies(this, aspect);return ancestor.widget;
  }
Copy the code

So dependOnInheritedWidgetOfExactType update didChangeDependencies method of dependent child widgets.

Consider the next question. Although the didChangeDependencies method is not called now, the build method of CountText is still executed. The reason is that changing the count value with setState in CountWidget will rebuild the child widgets used. But all we really want is to update the component value of the CountInheritedWidget that the child widget relies on.

So how to solve it? One solution offered here is to provide caching for child widgets. Child widgets can be cached by encapsulating a simple StatefulWidget. If you are interested in this area, look forward to my follow-up articles.

Recommended project

The following is a complete description of the Flutter project, which is a good introduction to the Flutter for beginners.

Flutter_github is a Github client based on Flutter that supports both Android and IOS, passwords and authentication login. Dart language was used for development, and the project architecture was MSVM based on Model/State/ViewModel. Use Navigator to jump to the page; The network framework uses DIO. The project is being updated continuously, those who are interested can follow it.

Of course, if you want to learn about Android native, flutter_Github’s pure Android version AwesomeGithub is a good choice.

If you like my article mode, or are interested in my next article, I suggest you follow my wechat official account: [Android supply station]

Or scan the qr code below to establish effective communication with me and receive my update push faster and more accurately.