美文网首页
flutter-state生命周期探索

flutter-state生命周期探索

作者: 陆元伟 | 来源:发表于2023-01-17 16:40 被阅读0次

如今公司用flutter开发项目,写了几个月的业务,对于widget的生命周期也朦朦胧胧,如今得空来探知下。

测试界面


图片.png

最外层一个Scaffold包着父widget,是个StatefulBuilder,点击按钮父组件刷新,就会刷新StatefulBuilder
widget是个LifecycleStateful ,打印state生命周期的方法

class LifecycleDemoPage extends StatelessWidget {
  const LifecycleDemoPage({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        ...
        body: StatefulBuilder(builder: (context,setter){
          return Column(
            children: [
              ElevatedButton(onPressed: (){
                setter.call((){});
              }, child: Text('父组件刷新')),
              LifecycleStateful(),
            ],
          );
        }));
  }
}

class LifecycleStateful extends StatefulWidget {
  @override
  State<StatefulWidget> createState(){
    LogUtils.d("createState ${toStringShort()}#$hashCode");
    return  LifecycleStatefulState();
  }
}

class LifecycleStatefulState extends State<LifecycleStateful> {
  int click = 0;
  @override
  void initState() {
    super.initState();
    LogUtils.d("State initState ${toStringShort()}");
  }
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    LogUtils.d("State dispose ${toStringShort()}");
  }
  @override
  void deactivate() {
    // TODO: implement deactivate
    super.deactivate();
    LogUtils.d("State deactivate ${toStringShort()}");
  }
  @override
  void activate() {
    // TODO: implement activate
    super.activate();
    LogUtils.d("State activate ${toStringShort()}");
  }
  @override
  void reassemble() {
    // TODO: implement reassemble
    super.reassemble();
    LogUtils.d("State activate ${toStringShort()}");
  }
  @override
  void didChangeDependencies() {
    // TODO: implement didChangeDependencies
    super.didChangeDependencies();
    LogUtils.d("State didChangeDependencies ${toStringShort()}");
  }
  @override
  void didUpdateWidget(covariant LifecycleStateful oldWidget) {
    // TODO: implement didUpdateWidget
    super.didUpdateWidget(oldWidget);
    LogUtils.d("State didUpdateWidget ${toStringShort()}");
  }
  List<Widget> children =[];
  bool newChild = false;
  @override
  Widget build(BuildContext context) {
    LogUtils.d("State build ${toStringShort()}");

    if(children.isEmpty){
      children = [
        ElevatedButton(
            onPressed: () {
              setState(() {
                click++;
              });
            },
            child: Text("click $click")),
        ElevatedButton(
            onPressed: () {
              setState(() {
                children.add(Text("i am add"));
              });
            },
            child: Text("添加子child")),
        ElevatedButton(
            onPressed: () {
              setState(() {
                newChild=!newChild;
              });
            },
            child: Text("change")),
      ];
    }

    return newChild?ElevatedButton(onPressed: (){
      setState(() {
        newChild=!newChild;
      });
    }, child: Text('change')):Container(
      padding: EdgeInsets.all(16),
      child: Column(
        children:children ,
      ),
    );
  }
}

进入界面时LifecycleStateful生命周期方法调用输出

I/flutter ( 7336): LifecycleStateful.createState (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:38:14)
I/flutter ( 7336):LifecycleStatefulState.initState (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:48:14)
I/flutter ( 7336): LifecycleStatefulState.didChangeDependencies (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:78:14)
I/flutter ( 7336): LifecycleStatefulState.build (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:89:14)

结论:生命周期调用依次 createState ,State构造器,initState,didChangeDependencies,build方法

点击父组件刷新按钮,此时父控件刷新,作为子控件的LifecycleStateful生命周期方法调用输出

I/flutter (22291):  LifecycleStatefulState.didUpdateWidget (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:102:14)
I/flutter (22291):  LifecycleStatefulState.build (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:108:14)

父控件刷新,子控件LifecycleStateful会调用didUpdateWidget ,build

点击click,调用setState方法,只调用了build方法

I/flutter ( 7336):LifecycleStatefulState.build (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:89:14)

切换主题颜色后调用了didUpdateWidgetbuild方法

I/flutter (22291): LifecycleStatefulState.didUpdateWidget (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:92:14)
I/flutter (22291): LifecycleStatefulState.build (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:98:14)

返回退出,依次调用deactivatedispose 方法

I/flutter (22291):  LifecycleStatefulState.deactivate (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:78:14)
I/flutter (22291): LifecycleStatefulState.dispose (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:72:14)

可以看到从进入到退出initState只打印一次。类似ViewonAttachedToWindow方法,build方法
就类似draw方法每次刷新会调用。dispose方法类似onDetachedFromWindow。只不过View的生命周期方法还有其他,颗粒度更细些。

结论:生命周期开始调用initState,更新会多次调用builddidUpdateWidget ,销毁调用dispose

didChangeDependencies方法除进入界面调用,就没在调用过。看源码注释说是和InheritedWidget有关

/// Called when a dependency of this [State] object changes.
  ///
  /// For example, if the previous call to [build] referenced an
  /// [InheritedWidget] that later changed, the framework would call this
  /// method to notify this object about the change.
  ///

为此另写代码继承InheritedWidget 控件,
界面如下:就一个InheritedWidget包裹着一个Text,和一个按钮,
按钮点击一下,count+=1并刷新,

图片.png

示例代码

class ShareDataWidget  extends InheritedWidget {
  final int data; //需要在子树中共享的数据,保存点击次数
  ShareDataWidget({
    Key? key,
    required this.data,
    required Widget child,
  }) : super(key: key, child: child);

  //定义一个便捷方法,方便子树中的widget获取共享数据
  static ShareDataWidget? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
  }
//定义一个便捷方法,方便子树中的widget获取共享数据
  static ShareDataWidget? of2(BuildContext context) {
    //return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
    return (context.getElementForInheritedWidgetOfExactType<ShareDataWidget>()!.widget as ShareDataWidget );
  }
  //该回调决定当data发生变化时,是否通知子树中依赖data的Widget
  @override
  bool updateShouldNotify(covariant ShareDataWidget oldWidget) {
    // TODO: implement updateShouldNotify
    return false;
  }
}
class _TestWidget extends StatefulWidget {
  @override
  __TestWidgetState createState() => __TestWidgetState();
}

class __TestWidgetState extends State<_TestWidget> {
  @override
  Widget build(BuildContext context) {
    //使用InheritedWidget中的共享数据
    return Text(ShareDataWidget.of(context)!.data.toString());
    // return Text("aaa");
  }
  @override
  void didUpdateWidget(covariant _TestWidget oldWidget) {
    // TODO: implement didUpdateWidget
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget");
  }
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    //父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用。
    //如果build中没有依赖InheritedWidget,则此回调不会被调用。
    print("Dependencies change");
  }
}
class InheritedWidgetTestRoute extends BasePage {
  InheritedWidgetTestRoute({ super.title:"InheritedWidget数据共享"});
  int count = 0;
  @override
  Widget body(BuildContext context) {
    return  Center(
      child: ShareDataWidget( //使用ShareDataWidget
        data: count,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.only(bottom: 20.0),
              child: _TestWidget(),//子widget中依赖ShareDataWidget
            ),
            ElevatedButton(
              child: Text("Increment"),
              //每点击一次,将count自增,然后重新build,ShareDataWidget的data将被更新
              onPressed: () => setState(() => ++count),
            )
          ],
        ),
      ),
    );
  }
}

注意上面updateShouldNotify方法返回false,点击按钮后,子widget调用

 I/flutter (22291): didUpdateWidget
 I/flutter (22291): build

修改updateShouldNotify返回true

I/flutter (22291): didUpdateWidget
I/flutter (22291): Dependencies change
I/flutter (22291): build

结论:InheritedWidgetupdateShouldNotify返回false时,子widget也只调用didUpdateWidgetbuild
updateShouldNotify返回true时,子widget依次调用didUpdateWidgetdidChangeDependenciesbuild

相关文章

网友评论

      本文标题:flutter-state生命周期探索

      本文链接:https://www.haomeiwen.com/subject/khithdtx.html