Flutter中的InheritedWidget、InheritedModel

There are four kinds of widgets in Flutter

StatelessWidget
StatefullWidget
RenderObjectWidget
InheritedWidget


Among them, StatelessWidget and StatefulWidget are the most common ones, classified from the perspective of state management. RenderObjectWidget is the base class for all widgets that need to be rendered.

As for the last InheritedWidget, many beginners may not understand it, but it must be used in some slightly complex projects, so this article introduces the usage of InheritedWidget

InheritedWidget

To obtain the nearest instance of a particular type of inherited widget from a build context, use BuildContext.inheritFromWidgetOfExactType.
Inherited widgets, when referenced in this way, will cause the consumer to rebuild when the inherited widget itself changes state.


Under normal circumstances, child widgets cannot perceive changes of parent widgets alone. When parent state changes, all child widgets are rebuilt through their builds;

InheritedWidget can avoid this kind of global creation and realize local sub-widget update:
sub-widget gets from buildContext through BuildContext.inheritFromWidgetOfExactType and listens to the specified type of parent InheritedWidget, and rebuilds following its reconstruction

insert image description here

As shown in the figure above, click the C button, after the State changes, the Text of A can be refreshed separately, and B is not affected


code demo

Next, compare the difference between using or not using InheritedWidget through code:

insert image description here

 Click +, after the 0 above changes, the text part in the middle does not change.

traditional implementation

After clicking the button state changes, widgetA, B, C will rebuild

class TopPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Demo'),
        ),
        body: HomePage(),
      ),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          WidgetA(_counter),
          WidgetB(),
          WidgetC(_incrementCounter),
        ],
      ),
    );
  }
}

class WidgetA extends StatelessWidget {
  final int counter;

  WidgetA(this.counter);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        '${counter}',
        style: Theme.of(context).textTheme.display1,
      ),
    );
  }
}

class WidgetB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('I am a widget that will not be rebuilt.');
  }
}

class WidgetC extends StatelessWidget {
  final void Function() incrementCounter;

  WidgetC(this.incrementCounter);

  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {
        incrementCounter();
      },
      child: Icon(Icons.add),
    );
  }
}


Using the Flutter Performance of AndroidStudio, you can see that widgets A, B, and C all participated in the rebuild

insert image description here

Implemented using InheritedWidget

import 'package:flutter/material.dart';

class TopPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(
        child: Scaffold(
          appBar: AppBar(
            title: Text('InheritedWidget Demo'),
          ),
          body: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              WidgetA(),
              WidgetB(),
              WidgetC(),
            ],
          ),
        ),
      ),
    );
  }
}


class _MyInheritedWidget extends InheritedWidget {

  final HomePageState data;

  _MyInheritedWidget({ Key key, Widget child, this.data }) : super(key: key, child: child);

  @override
  bool updateShouldNotify(_MyInheritedWidget oldWidget) {
    return true;
  }

}

class HomePage extends StatefulWidget {

  final Widget child;

  const HomePage({Key key, @required this.child}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return HomePageState();
  }

  static HomePageState of(BuildContext context, {bool rebuild = true}) {
    if (rebuild) {
      return context.dependOnInheritedWidgetOfExactType<_MyInheritedWidget>().data;
    }
    return context.findAncestorWidgetOfExactType<_MyInheritedWidget>().data;
    // or
    // return (context.getElementForInheritedWidgetOfExactType<_MyInheritedWidget>().widget as _MyInheritedWidget).data;
  }
}

class HomePageState extends State<HomePage> {
  int counter = 0;

  void _incrementCounter() {
    print('HomePageState before _incrementCounter counter $counter');
    setState(() {
      counter++;
      print('HomePageState counter $counter');
    });
  }

  @override
  Widget build(BuildContext context) {
    return _MyInheritedWidget(
      data: this,
      child: widget.child,
    );
  }
}



class WidgetA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final HomePageState state = HomePage.of(context);

    return Center(
      child: Text(
        '${state?.counter}',
        style: Theme.of(context).textTheme.headline4,
      ),
    );
  }
}

class WidgetB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('I am a widget that will not be rebuilt.');
  }
}

class WidgetC extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final HomePageState state = HomePage.of(context, rebuild: false);

    return RaisedButton(
      onPressed: () {
        state?._incrementCounter();
      },
      child: Icon(Icons.add),
    );
  }
}

Note: This demo 2022.3.5 has been personally verified, and the flutter sdk version used is 1.22.4

 The following is the demo of the latest version of flutter sdk, which supports null-safety

import 'package:flutter/material.dart';

class TopPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(
        child: Scaffold(
          appBar: AppBar(
            title: Text('InheritedWidget Demo'),
          ),
          body: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              WidgetA(),
              WidgetB(),
              WidgetC(),
            ],
          ),
        ),
      ),
    );
  }
}


class _MyInheritedWidget extends InheritedWidget {

  final HomePageState data;

  _MyInheritedWidget({ Key? key, required Widget child, required this.data }) : super(key: key, child: child);

  @override
  bool updateShouldNotify(_MyInheritedWidget oldWidget) {
    return true;
  }

}

class HomePage extends StatefulWidget {

  final Widget child;

  const HomePage({Key? key, required this.child}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return HomePageState();
  }

  static HomePageState? of(BuildContext context, {bool rebuild = true}) {
    if (rebuild) {
      return context.dependOnInheritedWidgetOfExactType<_MyInheritedWidget>()?.data;
    }
    return context.findAncestorWidgetOfExactType<_MyInheritedWidget>()?.data;
    //or
    //return (context.getElementForInheritedWidgetOfExactType<_MyInheritedWidget>().widget as _MyInheritedWidget).data;
  }
}

class HomePageState extends State<HomePage> {
  int counter = 0;

  void _incrementCounter() {
    print('HomePageState before _incrementCounter counter $counter');
    setState(() {
      counter++;
      print('HomePageState counter $counter');
    });
  }

  @override
  Widget build(BuildContext context) {
    return _MyInheritedWidget(
      data: this,
      child: widget.child,
    );
  }
}



class WidgetA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final HomePageState? state = HomePage.of(context);

    return Center(
      child: Text(
        '${state?.counter}',
        style: Theme.of(context).textTheme.headline4,
      ),
    );
  }
}

class WidgetB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('I am a widget that will not be rebuilt.');
  }
}

class WidgetC extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final HomePageState? state = HomePage.of(context, rebuild: false);

    return RaisedButton(
      onPressed: () {
        state?._incrementCounter();
      },
      child: Icon(Icons.add),
    );
  }
}

It can be seen that when the state changes, widgetB and C are not rebuilt

insert image description here

Key code description

Explain the key classes in the InheritedWidget version

WidgetA、WidgetC

In the traditional version, WidgetA and C pass the state of the parent through the constructor and call back the
InheritedWidget version, which can be obtained by the following static methods

final HomePageState state = HomePage.of(context); // WidgetA
final HomePageState state = HomePage.of(context, rebuild: false);  // WidgetC

WidgetC is a Button that needs to get the callback method through the state, but does not need to be refreshed with the state change, so rebuild specifies false

Next, let's take a look at the static method HomePage.of to get the state in detail.

HomePage

static HomePageState of(BuildContext context, {bool rebuild = true}) {
    if (rebuild) {
      return context.dependOnInheritedWidgetOfExactType<_MyInheritedWidget>().data;
    }
    return context.findAncestorWidgetOfExactType<_MyInheritedWidget>().data;
    // or
    // return (context.getElementForInheritedWidgetOfExactType<_MyInheritedWidget>().widget as _MyInheritedWidget).data;
  }


HomePage.of is used to find the nearest _MyInheritedWidget through buildContext. Then you can get the state it holds with _MyInheritedWidget.

Several key methods to obtain the upper-level Widget are as follows:

method description
inheritFromWidgetOfExactType Get the nearest parent widget of a given type. The widget must be a subclass of InheritedWidget, and register the incoming context with the parent widget. When the parent widget changes, the widget held by this context will be rebuilt to obtain a new one from the widget. value. This is how child registers with InheritedWidget.
ancestorWidgetOfExactType It is only used to obtain the nearest parent widget of a given type, and will not rebuild due to changes in the parent widget
ancestorInheritedElementForWidgetOfExactType The function is the same as inheritFromWidgetOfExactType, but it will only look for subclasses of InheritedWidget, so you can find the superior Widget with O(1) complexity

The above method is outdated, the new version of flutter should be:

method description
dependOnInheritedWidgetOfExactType Get the nearest parent widget of a given type. The widget must be a subclass of InheritedWidget, and register the incoming context with the parent widget. When the parent widget changes, the widget held by this context will be rebuilt to obtain a new one from the widget. value. This is how child registers with InheritedWidget.
findAncestorWidgetOfExactType It is only used to obtain the nearest parent widget of a given type, and will not rebuild due to changes in the parent widget
getElementForInheritedWidgetOfExactType The function is the same as findAncestorWidgetOfExactType, but it will only find subclasses of InheritedWidget, so you can find the superior Widget with O(1) complexity

Therefore, widgetA rebuilds as the parent widget changes, and widgetB does not rebuild

class _MyInheritedWidget extends InheritedWidget {
  _MyInheritedWidget({
    Key key,
    @required Widget child,
    @required this.data,
  }) : super(key: key, child: child);

  final HomePageState data;

  @override
  bool updateShouldNotify(_MyInheritedWidget oldWidget) {
    return true;
  }
}


Inherited from InheritedWidget, so child widgets can be obtained through dependOnInheritedWidgetOfExactType.

updateShouldNotify controls whether the child widget needs to feel its changes. If it returns true, the child widget registered through dependOnInheritedWidgetOfExactType will rebuild following its changes.

The ultimate purpose of the child widget is to obtain the shared parent state, so the state is held here through the data attribute.

Then take a look at this HomePageState

HomePageState

  @override
  Widget build(BuildContext context) {
    return _MyInheritedWidget(
      data: this,
      child: widget.child,
    );
  }


The use of _MyInheritedWidget is the key here.

In the traditional writing method, widgets A, B, and C are created directly in the build and returned, so whenever the state changes, the child widgets will be recreated and rebuilt;

In the InheritedWidget version, HomePage keeps the children of the parent widget (TopPage). When the state changes, widgets A, B, and C will not be rebuilt, but will be re-passed to _MyInheritedWidget, and only _MyInheritedWidget will be rebuilt.

TopPage

class TopPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    ・・・
          body: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[ 
              WidgetA(), // 子widget的创建移动到这里
              WidgetB(),
              WidgetC(),
            ],
          ),
    ・・・
  }
}


According to the above description, in order to avoid repeated creation and rebuilding of child widgets, move the instantiations of widgets A, B, and C to here
 

InheritedModel

In the above example, we specify whether the sub-Widget participates in the rebuild by customizing the rebuild parameter. In fact, InheritedModel can also be used to complete this requirement.

InheritedModel inherits from InheritedWidget, and can specify a specific child widget to rebuild through the string key (aspect).

A brief look at the difference in implementation between the InheritedModel version and the InheritedWidget version

   @override
   HomePageState createState() => HomePageState();

   static HomePageState of(BuildContext context, String aspect) {
     return InheritedModel.inheritFrom<_MyInheritedWidget>(context, aspect: aspect).data;
   }
 }


Use InheritedModel.inheritFrom to get the widget

class _MyInheritedWidget extends InheritedModel {

   @override
   bool updateShouldNotifyDependent(_MyInheritedWidget old, Set aspects) {
     return aspects.contains('A'); // 当aspect包晗“A”时,通知其rebuild
   }
 }


Inherit InheritedModel, override updateShouldNotifyDependent

 class WidgetA extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     final HomePageState state = HomePage.of(context, 'A'); // 注册aspect为“A“



 class WidgetC extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
    final HomePageState state = HomePage.of(context, 'C'); // 注册aspect为“C”


As above, because the registered key (aspect) is different, only widgetA will be notified of rebuild

The complete code is as follows:

import 'package:flutter/material.dart';

class TopPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(
        child: Scaffold(
          appBar: AppBar(
            title: Text('InheritedWidget Demo'),
          ),
          body: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              WidgetA(),
              WidgetB(),
              WidgetC(),
            ],
          ),
        ),
      ),
    );
  }
}


class _MyInheritedWidget extends InheritedModel {

  final HomePageState data;

  _MyInheritedWidget({ Key key, Widget child, this.data }) : super(key: key, child: child);

  @override
  bool updateShouldNotifyDependent(covariant InheritedModel oldWidget, Set dependencies) {
    return dependencies.contains('A'); // 当dependencies包晗“A”时,通知其rebuild
  }

  @override
  bool updateShouldNotify(covariant InheritedWidget oldWidget) {
    return true;
  }

}

class HomePage extends StatefulWidget {

  final Widget child;

  const HomePage({Key key, @required this.child}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return HomePageState();
  }

  static HomePageState of(BuildContext context, String aspect) {
    return InheritedModel.inheritFrom<_MyInheritedWidget>(context, aspect: aspect).data;

  }
}

class HomePageState extends State<HomePage> {
  int counter = 0;

  void _incrementCounter() {
    print('HomePageState before _incrementCounter counter $counter');
    setState(() {
      counter++;
      print('HomePageState counter $counter');
    });
  }

  @override
  Widget build(BuildContext context) {
    return _MyInheritedWidget(
      data: this,
      child: widget.child,
    );
  }
}



class WidgetA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final HomePageState state = HomePage.of(context, 'A');

    return Center(
      child: Text(
        '${state?.counter}',
        style: Theme.of(context).textTheme.headline4,
      ),
    );
  }
}

class WidgetB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('I am a widget that will not be rebuilt.');
  }
}

class WidgetC extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final HomePageState state = HomePage.of(context, 'C');
    print('WidgetC counter ${state.counter}');

    return RaisedButton(
      onPressed: () {
        state?._incrementCounter();
      },
      child: Icon(Icons.add),
    );
  }
}


more local refresh

If widgetA is as follows, we want to further control the partial refresh of its child widgets

class WidgetA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final HomePageState state = HomePage.of(context);

    return Column(
      children: <Widget>[
        Center(
          child: Text(
            '${state.counter}',
            style: Theme.of(context).textTheme.display1,
          ),
        ),
        Text("AAAAA"), // 此处不需rebuild
      ],
    );
  }
}


If you thoroughly understand the registration mechanism of BuildContext and InheritedWidget, it can be easily implemented:

 return Column(
      children: <Widget>[
        Center(
          child: Builder(builder: (context){
            final HomePageState state = HomePage.of(context);
            return Text(
              '${state.counter}',
              style: Theme.of(context).textTheme.display1,
            );
          }),
        ),
        Text("AAAAA"),
      ],
    );

Create an anonymous class widget through Builder, and then move HomePage.of inside it. At this time, the context registered in InheritedWidget is no longer widgetA but this anonymous class widget, so the partial refresh of widgetA can be realized


Not using InheritedWidget

I think through the above introduction, you should be able to think that if the child widget only wants to access the parent state (without passing parameters through the constructor), but there is no need to monitor its changes, you can not use InheritedWidget:

class TopPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Demo'),
        ),
        body: HomePage(),
      ),
    );
  }
}

class HomePage extends StatefulWidget {
  HomePageState state; // 持有state供子类获取

  @override
  HomePageState createState() {
    state = HomePageState();
    return state;
  }
}

class HomePageState extends State<HomePage> {
  int counter = 0; // 去掉private

  void incrementCounter() { // 去掉private
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          WidgetA(),
          WidgetB(),
          WidgetC(),
        ],
      ),
    );
  }
}

class WidgetA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final HomePage widget = context.ancestorWidgetOfExactType(HomePage); // 获取state
    final HomePageState state = widget?.state;

    return Center(
      child: Text(
        '${state == null ? 0 : state.counter}',
        style: Theme.of(context).textTheme.display1,
      ),
    );
  }
}

class WidgetB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('I am a widget that will not be rebuilt.');
  }
}

class WidgetC extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final HomePage widget = context.ancestorWidgetOfExactType(HomePage);
    final HomePageState state = widget?.state;

    return RaisedButton(
      onPressed: () {
        state?.incrementCounter();
      },
      child: Icon(Icons.add),
    );
  }
}

Find the specified type of widget through ancestorWidgetOfExactType, and then get its state for use. Of course, this traversal is O(n), and the performance is worse than the InheritedWidget version


finally

Many components in Flutter are implemented based on InheritedWidget, such as Scoped Model, BLoC (Business Logic of component), etc. To master the use of these advanced features, start by understanding InheritedWidget

Code:
https://github.com/vitaviva/flutter_inherited_widget_sample/tree/master/flutter_inherited_widget https://github.com/vitaviva/flutter_inherited_widget_sample/tree/master/flutter_inherited_widget


Extension:
Flutter uses InheritedModel to achieve partial refresh

The defined data model is

import 'package:flutter/material.dart';
import 'user_type.dart';
 
class UserInheritedModel extends InheritedModel<UserType> {
  final int age;
  final int weight;
 
  const UserInheritedModel(
      {required this.age, required this.weight, required Widget child})
      : super(child: child);
 
  static UserInheritedModel? of(BuildContext context,
      {required UserType aspect}) {
    return InheritedModel.inheritFrom<UserInheritedModel>(context,
        aspect: aspect);
  }
 
  @override
  bool updateShouldNotify(UserInheritedModel old) {
    return age != old.age || weight != old.weight;
  }
 
  @override
  bool updateShouldNotifyDependent(
      UserInheritedModel old, Set<UserType> aspects) {
    return (aspects.contains(UserType.age) && age != old.age) ||
        (aspects.contains(UserType.height) && weight != old.weight);
  }
}

The page to be partially refreshed is

Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              InkWell(
                child: const AgePage(
                  ideaType: UserType.age,
                ),
                onTap: () {
                  setState(() {
                    _age += 1;
                  });
                },
              ),
              Divider(),
              InkWell(
                child: const WeightPage(
                  ideaType: UserType.height,
                ),
                onTap: () {
                  setState(() {
                    _weight += 1;
                  });
                },
              ),
            ],
          ),

Included pages are

 
class AgePage extends StatelessWidget {
  final UserType ideaType;
 
  const AgePage({Key? key, required this.ideaType}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    final UserInheritedModel? _ideasTypeIdea =
        UserInheritedModel.of(context, aspect: ideaType);
 
    return Text(
      '${_ideasTypeIdea!.age}\n${Random.secure().nextDouble()}',
    );
  }
}
Another page similar to the above


What is InheritedWidget and How it works in a Flutter??

 The above article introduces the implementation principle of InheritedWidget, and the modified demo is posted below for reference.

import 'package:flutter/material.dart';

class MyStatefulWidget extends StatefulWidget {
  final Widget child;

  const MyStatefulWidget({Key key, @required this.child}) : super(key: key);

  static MyStatefulWidgetState of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>().data;
  }

  @override
  State<StatefulWidget> createState() {
    return MyStatefulWidgetState();
  }
}

class MyStatefulWidgetState extends State<MyStatefulWidget> {
  int _counterValue = 0;

  int get counterValue => _counterValue;

  void addCounterBy() {
    setState(() {
      _counterValue += 1;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MyInheritedWidget(
      child: widget.child,
      data: this,
    );
  }
}

class MyInheritedWidget extends InheritedWidget {
  final MyStatefulWidgetState data;

  MyInheritedWidget({
    Key key,
    @required Widget child,
    @required this.data,
  }) : super(key: key, child: child);

  @override
  bool updateShouldNotify(InheritedWidget oldWidget) {
    return true;
  }
}

class MyContainer extends StatelessWidget {
  final Widget child;

  MyContainer({
    Key key,
    @required this.child,
  })  : super(key: key);

  void onPressed(BuildContext context) {
    MyStatefulWidget.of(context).addCounterBy();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        width: 200,
        height: 200,
        child: RaisedButton(
          color: Colors.red,
          onPressed: (){
            onPressed(context);
          },
          child: child,
        ),
      ),
    );
  }
}

class DummyContainer extends StatelessWidget {
  final Widget child;

  const DummyContainer({Key key, this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return child;
  }
}

class WidgetA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text(
      "Counter",
      style: TextStyle(
        color: Colors.white,
        fontSize: 20,
      ),
    );
  }
}

class WidgetB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('I am a widget that will not be rebuilt.',
      style: TextStyle(
        fontSize: 14,
        color: Colors.white,
      ),);
  }
}

class WidgetC extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return CounterValueState();
  }
}

class CounterValueState extends State<WidgetC> {
  int counterValue;
  double fontSize;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    MyStatefulWidgetState data = MyStatefulWidget.of(context);
    counterValue = data.counterValue;
    fontSize = 50.0 + counterValue;
  }

  @override
  Widget build(BuildContext context) {
    return Text(
      "$counterValue",
      style: TextStyle(
        fontSize: fontSize,
        color: Colors.white,
      ),
    );
  }
}

Guess you like

Origin blog.csdn.net/jdsjlzx/article/details/123263801