前言:生命周期是一个组件加载到卸载的整个周期,熟悉生命周期可以让我们在合适的时机做该做的事情,
flutter中的State生命周期和android以及React Native的生命周期类似。

先看一张生命周期的流程图:


大致可以分为3个阶段:

初始化
状态变化
组件移除
初始化
State初始化时会依次执行 : 构造函数 > initState > didChangeDependencies > Widget build , 此时页面加载完成。

然后我们看一下每个函数的意义:

构造函数
调用次数:1次

这个函数严格意义上来讲不属于生命周期的一部分,因为这个时候State的widget属性为空,无法在构造函数中访问widget的属性 。但是构造函数必然是要第一个调用的。可以在这一部分接收前一个页面传递过来的数据。

initState
Called when this object is inserted into the tree.

调用次数:1次

当插入渲染树的时候调用,这个函数在生命周期中只调用一次。这里可以做一些初始化工作,比如初始化State的变量。

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

初始化时,在initState()之后立刻调用
当依赖的InheritedWidget rebuild,会触发此接口被调用
这个函数会紧跟在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中,可以跨组件拿到数据。

#运行时

build
调用次数:多次

初始化之后开始绘制界面,当setState触发的时候会再次被调用

didUpdateWidget
Called whenever the widget configuration changes.

祖先节点rebuild widget时调用 .当组件的状态改变的时候就会调用didUpdateWidget.

理论上setState的时候会调用,但我实际操作的时候发现只是做setState的操作的时候没有调用这个方法。而在我改变代码hot reload时候会调用 didUpdateWidget 并执行 build…

实际上这里flutter框架会创建一个新的Widget,绑定本State,并在这个函数中传递老的Widget。
这个函数一般用于比较新、老Widget,看看哪些属性改变了,并对State做一些调整。

需要注意的是,涉及到controller的变更,需要在这个函数中移除老的controller的监听,并创建新controller的监听。

组件移除
组件移除,例如页面销毁的时候会依次执行:deactivate > dispose

deactivate
Called when this object is removed from the tree.

在dispose之前,会调用这个函数。实测在组件可见状态变化的时候会调用,当组件卸载时也会先一步dispose调用。

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

调用次数:1次

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

##reassemble
hot reload调用

名称 状态
initState 插入渲染树时调用,只调用一次
didChangeDependencies state依赖的对象发生变化时调用
didUpdateWidget 组件状态改变时候调用,可能会调用多次
build 构建Widget时调用
deactivate 当移除渲染树的时候调用
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页面移除。

本次示例B页面代码:

import 'package:flutter/material.dart';

class NewsDetailPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => NewsDetailState();
} class NewsDetailState extends State<NewsDetailPage> {
int text = 1; NewsDetailState() {
print('构造函数');
} @override
void initState() {
print('init state');
super.initState();
} @override
void didChangeDependencies() {
print('didChangeDependencies');
super.didChangeDependencies();
} @override
Widget build(BuildContext context) {
print('widget build'); return Scaffold(
body: Center(
child: _loading(),
),
appBar: AppBar(
title: Text('咨询详情'),
),
);
} @override
void didUpdateWidget(NewsDetailPage oldWidget) {
print('组件状态改变:didUpdateWidget');
super.didUpdateWidget(oldWidget);
} @override
void deactivate() {
print('移除时:deactivate');
super.deactivate();
} @override
void dispose() {
print('移除时:dispose');
super.dispose();
} //预加载布局
Widget _loading() {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(
strokeWidth: 1.0,
),
Container(
child: Text("正在加载"),
margin: EdgeInsets.only(top: 10.0),
)
],
);
}
}

  

Tips:
下面内容来自咸鱼技术团队.

当ListView中的item滚动出可显示区域的时候,item会被从树中remove掉,此item子树中所有的state都会被dispose,state记录的数据都会销毁,item滚动回可显示区域时,会重新创建全新的state、element、renderobject

使用hot reload功能时,要特别注意state实例是没有重新创建的,如果该state中存在一下复杂的资源更新需要重新加载才能生效,那么需要在reassemble()添加处理,不然当你使用hot reload时候可能会出现一些意想不到的结果,例如,要将显示本地文件的内容到屏幕上,当你开发过程中,替换了文件中的内容,但是hot reload没有触发重新读取文件内容,页面显示还是原来的旧内容.

didChangeDependencies有两种情况会被调用。

创建时候在initState 之后被调用

在依赖的InheritedWidget发生变化的时候会被调用

正常的退出流程中会执行deactivate然后执行dispose。但是也会出现deactivate以后不执行dispose,直接加入树中的另一个节点的情况。

这里的状态改变包括两种可能:1.通过setState内容改变 2.父节点的state状态改变,导致孩子节点的同步变化。

App生命周期
需要指出的是如果想要知道App的生命周期,那么需要通过WidgetsBindingObserver的didChangeAppLifecycleState 来获取。通过该接口可以获取是生命周期在AppLifecycleState类中。常用状态包含如下几个:

名称 状态
resumed 可见并能响应用户的输入
inactive 处在并不活动状态,无法处理用户响应
paused 不可见并不能响应用户的输入,但是在后台继续活动中

一个实际场景中的例子:

在不考虑suspending的情况下:从后台切入前台生命周期变化如下: AppLifecycleState.inactive->AppLifecycleState.resumed;

从前台压后台生命周期变化如下: AppLifecycleState.inactive->AppLifecycleState.paused;

原文:https://blog.csdn.net/u011272795/article/details/82695920

flutter中的生命周期函数的更多相关文章

  1. ionic中的生命周期函数

    //ionic中的生命周期函数 onPageLoaded(){ //page初始化时 console.log("page 1 : page loaded"); } //在这里可以做 ...

  2. Angular 中的生命周期函数

    一. Angular中的生命周期函数 官方文档:https://www.angular.cn/guide/lifecycle-hooks 生命周期函数通俗的讲就是组件创建.组件更新.组件销毁的时候会触 ...

  3. Unity3D中的生命周期函数

    生命周期函数:需要继承 MonoBehaviour 类才能使用.生命周期函数全部都是由系统定义好的,系统会自动调用,且调用顺序和我们在代码里面的书写顺序无关. 常用的生命周期函数: Awake():唤 ...

  4. React中的生命周期函数

    React的生命周期函数 什么是生命周期函数:生命周期函数是指在某一个时刻组件会自动调用执行的函数 Initialization:初始化 执行Constructor,初始state和props Mou ...

  5. ionic生命周期函数

    Ionic4中的生命周期函数和angualr7基本是一样的,下面我们看看Ionic4中的生命周期函数,以及生命周期函数的用法. Ionic4中内置的生命周期函数: ionViewWillEnter — ...

  6. React的生命周期函数

    概述 在React中,生命周期函数指的是组件在某一个时刻会自动执行的函数 constructor 在类或组件创建的时候被自动执行,我们可以说它是生命周期函数,但它并不是React所特有的,所有的Es6 ...

  7. 【老孟Flutter】Flutter 中与平台相关的生命周期

    老孟导读:关于生命周期的文章共有2篇,一篇(此篇)是介绍 Flutter 中Stateful 组件的生命周期. 第二篇是 Flutter 中与平台相关的生命周期, 博客地址:http://laomen ...

  8. Activity系列讲解---三大基本状态与七大生命周期函数

    简介:四大组件之一,在应用中一个Activity可以用来表示一个界面,可以理解为用户可视化界面,一个android应用必须通过Activity来运行和启动. 1.三大基本状态与七大生命周期函数 2.代 ...

  9. Cocos2d-x场景生命周期函数介绍

    层(Layer)的生命周期函数有如下: init().初始化层调用. onEnter().进入层时候调用. onEnterTransitionDidFinish().进入层而且过渡动画结束时候调用. ...

随机推荐

  1. sql简易教程

    讲干货,不啰嗦,本教程主要基于Mysql数据库,讲解sql的基本使用. 数据库主要包括增.删.改.查等基本操作,以下为设计到的常用的sql语句: 一.查 1.select 语法查询 SELECT co ...

  2. 安卓开发之SimpleAdapter的使用

    package com.lidaochen.test; import android.support.v7.app.AppCompatActivity; import android.os.Bundl ...

  3. 如何上传HTML5应用到SAP云平台的Cloud Foundry环境下

    先使用WebIDE创建一个HTML5应用.New->Project from Template: 从可选模板里选择SAPUI5 Application: 创建一个HTML5 Module,取名为 ...

  4. 【ASE高级软件工程】第一次结对作业

    问题定义 具体规则见:讲义.大致规则如下: N个同学(N通常大于10),每人写一个0~100之间的有理数 (不包括0或100),交给裁判,裁判算出所有数字的平均值,然后乘以0.618(所谓黄金分割常数 ...

  5. phpstorm 习惯设置

    phpstorm 习惯设置 1. 字体:Source Code Pro 大小:14 链接: https://pan.baidu.com/s/1HLpbduBHFvbq1a10QV4uCg 提取码: y ...

  6. 阿里云Ubuntu下tomcat8.5配置SSL证书

    环境 阿里云ubuntu(18.04)服务器 阿里云申请的域名 Tomcat8.5.7 jdk1.8 免费型SSL证书 SSL证书申请 登录阿里云的官网,登录后在菜单中选择SSL证书(应用安全) 进入 ...

  7. 《数字图像处理(MATLAB)》冈萨雷斯

    <数字图像处理(MATLAB)>冈萨雷斯 未完结! 参考:数字图像处理——https://blog.csdn.net/dujing2019/article/category/8820151 ...

  8. Django框架起步

    一.环境安装 二.创建项目 三.项目目录 四.创建项目应用 五.应用目录 六.第一个响应 七.第一个模板页面 八.第一个重定向 九.url应用移植 十.多应用相同模板页面冲突 十一.静态资源的配置 十 ...

  9. ACM-ICPC 2018 焦作赛区网络预赛 K. Transport Ship(DP)

    题目链接:https://nanti.jisuanke.com/t/31720 题意:有n种飞船,每种飞船有(1 << c)- 1  艘,容量为 k[i] ,q 次询问,每次询问选若干艘飞 ...

  10. django.core.exceptions.ImproperlyConfigured: The included URLconf 's9luffycity.urls' does not appear to have any patterns in it. If you see valid patterns in the file then the issue is probably caused

    出现问题: $ python manage.py runserver 启动项目报错时候 raise ImproperlyConfigured(msg.format(name=self.urlconf_ ...