FlutterComponent最佳实践之Widget Lifecycle

1b5cad89a826eb774fdeff2febf7cd00.png

点击上方蓝字关注我,知识会给你力量

01ae83599ab8c9e5db28a44dc6069dac.png

了解Flutter的生命周期,是我们写出优雅的App的基石,通过生命周期的适配,可以让代码更加稳健,鲁棒性更好。

Widget生命周期

下面这张图,就展示了一个Widget的整体生命周期示例。
23c1c89a71665128760b17cdff56b0ae.png
当你把BuildContext分配给Widget时,一个内部标志位—mounted会被设置为true。这会让Framework知道这个Widget目前已经挂载到Widget Tree上。下面我们分三个方面来看下Widget生命周期的处理过程。

创建

Widget会依次经历initState->didChangeDependencies->build三个过程。

initState()是一个Widget被创建后调用的第一个方法。这类似于Android的onCreate()或iOS的viewDidLoad()方法。

在Framework第一次构建一个Widget时,它会在initState()之后调用didChangeDependencies()方法。如果你的Widget state依赖于一个InheritedWidget,它可能会再次调用didChangeDependencies()。

最后,框架在didChangeDependencies()之后调用build()方法。这个方法对开发者来说是最重要的,因为每次有Widget需要渲染时,都会调用这个方法。Widget Tree上的每个Widget都会递归地触发build()方法,所以这个方法内部的操作必须非常快。

所以,你应该总是将繁重的计算功能异步执行,并将其结果存储为state的一部分,以便后面与build()方法一起使用。build()方法不应该做任何有计算要求的事情。这类似于你对iOS或Android主线程的概念,例如,你不应该在主线程请求一个网络调用,这样使UI渲染停滞。

更新

Widget在更新时,主要会经历setState->didchangeDependencies->didUpdateWidget三个过程。

每当你想修改你的Widget的状态时,你可以调用setState()方法。然后Framework会将该Widget标记为「dirty」,并再次触发build()方法。

异步代码应该总是在调用setstate()之前,检查mounted属性是否为true,因为该Widget在异步执行后,可能不再是Widget Tree的一部分来了。

当父Widget change时或需要重新绘制用户界面时,或者是热重载时,框架会调用didUpdateWidget方法。当这种情况发生时,你会得到oldWidget实例作为参数,这样你就可以把它和你当前的widget进行比较,并做任何额外的逻辑。

当State对象的依赖关系发生改变时,例如系统Local或者Theme发生改变时,Framework就会回调didChangeDependencies方法。

一旦这些方法被调用,Framework就会销毁Old Widget,并执行新的Widget的build方法。

销毁

当你从Widget Tree中移除对象时,Framework会调用deactivate()方法。在某些情况下,Framework可以将state对象重新插入到Widget Tree的另一部分。

当你从Widget Tree上永久地移除某个Widget及其state时,框架会调用dispose()方法。这个方法非常重要,因为你需要它来清理内存,比如取消订阅流和处理动画或控制器。

在dispose()方法中,你应该检查你在state中定义的任何属性,并确保你已经正确处置了它们。

App生命周期

前面我们分析了Widget的生命周期,而对于App来说,它的生命周期则更复杂一些。在Android中,我们通常需要处理onCreate、onPause、onResume这些生命周期回调方法,而在Flutter中,我们可以通过WidgetsBindingObserver来实现生命周期的监听。
658ec79c5829da78b4e74a79268a5dd4.png

didChangeAppLifecycleState

didChangeAppLifecycleState是App生命周期的回调方法,它提供了AppLifecycleState的枚举:

  • resumed:可见的,并能响应用户的输入。

  • inactive:处在不活动状态,无法处理用户响应。

  • paused:不可见并不能响应用户的输入,但是在后台继续活动中。

class _MyAppState extends State<MyApp> with WidgetsBindingObserver {

  @override
  void initState() {
    WidgetsBinding.instance.addObserver(this);
    super.initState();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    print('didChangeAppLifecycleState $state');
    super.didChangeAppLifecycleState(state);
  }

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

当我们退到后台时:

didChangeAppLifecycleState AppLifecycleState.inactive
didChangeAppLifecycleState AppLifecycleState.paused

再回到前台时:

didChangeAppLifecycleState AppLifecycleState.resumed

帧渲染完成回调

Flutter对帧的绘制回调进行了封装,通过WidgetsBinding,我们可以很方便的获取单次的帧绘制回调和实时的帧绘制回调。

WidgetsBinding.instance.addPostFrameCallback((timeStamp) {});
WidgetsBinding.instance.addPersistentFrameCallback((timeStamp) {});

通过这两个回调,我们既可以获取单次的Frame渲染完成的节点,也可以获取每次渲染完成的节点,从而实现FPS的监听。

向大家推荐下我的网站 https://www.yuque.com/xuyisheng  点击原文一键直达

专注 Android-Kotlin-Flutter 欢迎大家访问

往期推荐

本文原创公众号:群英传,授权转载请联系微信(Tomcat_xu),授权后,请在原创发表24小时后转载。

< END >

作者:徐宜生

更文不易,点个“三连”支持一下👇

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值