• Flutter widget生命周期详解


    前言

    和其他的视图框架比如android的Activity一样,flutter中的视图Widget也存在生命周期,生命周期的回调函数提现在了State上面。理解flutter的生命周期,对我们写出一个合理的控件至关重要。组件State的生命周期整理如下图所示:


     
    Widget 生命周期

    大致可以看成三个阶段

    • 初始化(插入渲染树)
    • 状态改变(在渲染树中存在)
    • 销毁(从渲染树种移除)

    构造函数

    这个函数不属于生命周期,因为这个时候State的widget属性为空,如果要在构造函数中访问widget的属性是行不通的。但是构造函数必然是要第一个调用的。

    initState

    /// Called when this object is inserted into the tree.
    当插入渲染树的时候调用,这个函数在生命周期中只调用一次。这里可以做一些初始化工作,比如初始化State的变量。

    didChangeDependencies

    /// Called when a dependency of this [State] object changes.

     
    didChangeDependencies

    这个函数会紧跟在initState之后调用,并且可以调用BuildContext.inheritFromWidgetOfExactType,那么BuildContext.inheritFromWidgetOfExactType的使用场景是什么呢?最经典的应用场景是
    new DefaultTabController(length: 3, child: new TabBar(
          tabs: [ "主页","订单","我的" ]
          .map( (data)=>new Text(data) ).toList(),
    

    TabBar本来需要定义一个TabController,但是在外面套一层DefaultTabController就不需要定义TabContrller了,看下源码:

    @override
      void didChangeDependencies() {
        super.didChangeDependencies();
        _updateTabController();
        _initIndicatorPainter();
      }
    
    void _updateTabController() {
        final TabController newController = widget.controller ?? DefaultTabController.of(context);
    

    注意到这里DefaultTabController.of(context)

     static TabController of(BuildContext context) {
        final _TabControllerScope scope = context.inheritFromWidgetOfExactType(_TabControllerScope);
        return scope?.controller;
      }
    

    实际上就是调用BuildContext.inheritFromWidgetOfExactType,也就说在didChangeDependencies中,可以跨组件拿到数据。

    didUpdateWidget

    /// Called whenever the widget configuration changes.

     
    didUpdateWidget

    当组件的状态改变的时候就会调用didUpdateWidget,比如调用了setState.
    实际上这里flutter框架会创建一个新的Widget,绑定本State,并在这个函数中传递老的Widget。
    这个函数一般用于比较新、老Widget,看看哪些属性改变了,并对State做一些调整。
    需要注意的是,涉及到controller的变更,需要在这个函数中移除老的controller的监听,并创建新controller的监听。
     
    TabBar_didUpdateWidget

     
    _updateTabController

    deactivate

    /// Called when this object is removed from the tree.

    在dispose之前,会调用这个函数。

    dispose

    /// Called when this object is removed from the tree permanently.

    一旦到这个阶段,组件就要被销毁了,这个函数一般会移除监听,清理环境。
    还是TabBar:


     
    dispose

    实际场景

    假设我们从A页面跳转到B页面, 那么A,B页面的生命周期会是怎样的呢?

    B页面进入初始化状态,依次执行4个函数:构造函数 > initState > didChangeDependencies > Widget build , 此时页面加载完成,进入运行态。
    此时A页面依次执行deactivate > build函数。注意 此时A页面并未卸载。

    然后我们假设B页面只有一个按钮,点击B页面中的按钮,改变按钮的文字,会执行widget的build方法 ,(理论上也应该执行didUpdateWidget,但我这里没有)。

    这时,我们点击返回键从B页面返回到A页面。
    A页面重新显示,B页面开始卸载。
    那么A先执行deactivate > build , 然后B页面依次执行:deactivate > dispose 。
    此时A页面进入运行态,B页面移除。

    总结一下

    阶段调用次数是否支持setState
    构造函数 1
    initState 1 无效(使用setState和不使用一样)
    didChangeDependencies >=1 无效
    didUpdateWidget >=1
    deactivate >=1
    dispose 1


    作者:ershixiong
    链接:https://www.jianshu.com/p/762bb2b7fa00
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    返回一个整数数组中最大子数组的和(数组头尾连接)
    场景调研(补)
    《浪潮之巅》读书笔记3
    《软件工程》课程改进意见
    【每日scrum】第一次冲刺day6
    【每日scrum】第一次冲刺day5
    【每日scrum】第一次冲刺day4
    【每日scrum】第一次冲刺day3
    【每日scrum】第一次冲刺day2
    【每日scrum】第一次冲刺day1
  • 原文地址:https://www.cnblogs.com/xiaochii/p/12709823.html
Copyright © 2020-2023  润新知