Flutter中的InheritedWidget、InheritedModel

Flutter中有四种widget

StatelessWidget
StatefullWidget
RenderObjectWidget
InheritedWidget


其中StatelessWidget和StatefulWidget是最常见到的,从状态管理角度的分类。RenderObjectWidget是所有需要渲染的Widget的基类。

至于最后一个InheritedWidget,许多初学者不一定了解,但是在一些稍微复杂的项目中是必须要用到的,所以本文介绍一下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.


通常情况下,子widget无法单独感知父widget的变化,当父state变化时,通过其build重建所有子widget;

InheritedWidget可以避免这种全局创建,实现局部的子widget更新:
子widget通过BuildContext.inheritFromWidgetOfExactType从buildContext中获取并监听指定类型的父InheritedWidget,并跟随其重建而rebuild

在这里插入图片描述

如上图,点击C按钮,State变化后,A的Text可以单独刷新,B不受到影响


代码演示

接下来通过代码对比一下使用或不使用InheritedWidget的区别:

在这里插入图片描述

 点击+,后上面的0变化,中间的文字部分不变化。

传统实现

点击按钮state变化后,widgetA、B、C都会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),
    );
  }
}


使用AndroidStudio的Flutter Performance可以看到widgetA、B、C都参与了rebuild

在这里插入图片描述

使用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),
    );
  }
}

注意:本demo 2022.3.5亲自验证通过,使用的flutter sdk版本位1.22.4

 下面是flutter sdk 最新版本demo,支持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),
    );
  }
}

可以看到state变化时,widgetB、C都没有rebuild

在这里插入图片描述

关键代码说明

针对InheritedWidget版本中的关键类进行说明

WidgetA、WidgetC

传统版本中WidgetA、C通过构造函数传入父级的state以及回调
InheritedWidget版本中,可以通过如下静态方法获取

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

WidgetC是一个Button需要通过state获取回调方法,但不需要跟随state变化而刷新,所以rebuild指定false

接下来详细看一下获取state的静态方法 HomePage.of

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用来通过buildContext,找到最近的_MyInheritedWidget。然后就可以同_MyInheritedWidget获取其持有的state。

获取上级Widget的几个关键方法如下:

methoddescription
inheritFromWidgetOfExactType获取最近的给定类型的上级Widget,该widget必须是InheritedWidget的子类,并向上级widget注册传入的context,当上级widget改变时,这个context持有的widget会rebuild以便从该widget获得新的值。这就是child向InheritedWidget注册的方法。
ancestorWidgetOfExactType仅仅用来获取最近的给定类型的上级Widget,不会因为上级Widget的改变而rebuild
ancestorInheritedElementForWidgetOfExactType功能与inheritFromWidgetOfExactType一样,但是只会寻找InheritedWidget的子类,所以可以以O(1)的复杂度查找上级Widget

上面的方法已经过时,flutter新版本的应该是:

methoddescription
dependOnInheritedWidgetOfExactType获取最近的给定类型的上级Widget,该widget必须是InheritedWidget的子类,并向上级widget注册传入的context,当上级widget改变时,这个context持有的widget会rebuild以便从该widget获得新的值。这就是child向InheritedWidget注册的方法。
findAncestorWidgetOfExactType仅仅用来获取最近的给定类型的上级Widget,不会因为上级Widget的改变而rebuild
getElementForInheritedWidgetOfExactType功能与findAncestorWidgetOfExactType一样,但是只会寻找InheritedWidget的子类,所以可以以O(1)的复杂度查找上级Widget

因此,widgetA随着父widget的变化而rebuild,widgetB并没有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;
  }
}


继承自InheritedWidget,所以子Widget可以通过dependOnInheritedWidgetOfExactType获取。

updateShouldNotify控制是否需要子widget感受其变化,如果返回true,则通过dependOnInheritedWidgetOfExactType注册的子widget跟随其变化rebuild

子widget最终目的是要获取共享的父级state,所以这里通过data属性持有了state。

那再来看一下这个HomePageState

HomePageState

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


此处_MyInheritedWidget的使用是关键。

传统写法中,build中直接创建widgetA、B、C并返回,因此每当state变化时,会重新创建子widget并rebuild;

InheritedWidget版本中,HomePage保持父widget(TopPage)的children,当state变化时widgetA、B、C不会重建,而是重新传入给_MyInheritedWidget,重建的只有_MyInheritedWidget

TopPage

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


根据上文的说明,为了避免子widget的反复创建和rebuild,将widgetA、B、C的实例化移动到这里
 

InheritedModel

上面的例子中我们通过自定义了rebuild参数来指定子Widget是否参与rebuild,实际上也可以使用InheritedModel完成此需求

InheritedModel继承自InheritedWidget,可以通过字符串key(aspect)来指定特定子widget进行rebuild。

简单看一下InheritedModel版本与InheritedWidget版本在实现上的不同

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

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


使用 InheritedModel.inheritFrom获取widget

class _MyInheritedWidget extends InheritedModel {

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


继承InheritedModel,重写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”


如上,因为注册的key(aspect)不同,只有widgetA会受到rebuild的通知

完整代码如下:

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),
    );
  }
}


更局部的刷新

如果widgetA是下面这样,我们希望能进一步控制其子widget的局部刷新

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
      ],
    );
  }
}


如果彻底理解了BuildContext和InheritedWidget的注册机制,是可以很容易实现的:

 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"),
      ],
    );

通过Builder来创建一个匿名类widget,然后将HomePage.of移到其内部。此时InheritedWidget中注册的context不再是widgetA而是这个匿名类widget,因此可以实现widgetA的局部刷新


不使用InheritedWidget

我想通过上文的介绍大家应该能够想到,如果子widget仅仅想访问父级state(不通过构造函数传参的方式),但没有监听其变化的需要,可以不使用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),
    );
  }
}

通过ancestorWidgetOfExactType寻找指定类型的widget,然后获取其state使用,当然这个遍历是O(n)的,性能比InheritedWidget版本要差


最后

Flutter中很多组件都是基于InheritedWidget实现的,例如Scoped Model、BLoC(Business Logic of component)等,想要掌握这些高级特性的使用先从了解InheritedWidget开始吧

代码:
https://github.com/vitaviva/flutter_inherited_widget_sample/tree/master/flutter_inherited_widgethttps://github.com/vitaviva/flutter_inherited_widget_sample/tree/master/flutter_inherited_widget


延伸:
Flutter使用InheritedModel实现局部刷新

定义的数据模型为

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);
  }
}

要局部刷新的页面为

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;
                  });
                },
              ),
            ],
          ),

包含的页面为

 
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()}',
    );
  }
}
另一个页面与上面的类似


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

 上面的文章介绍了InheritedWidget的实现原理,下面把改动过的demo贴出来,供参考。

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,
      ),
    );
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值