WidgetsBinding.instance.addPostFrameCallback 如何使用

最近开发 Flutter 项目学到一个非常好用的方法或者说函数 WidgetsBinding.instance.addPostFrameCallback。它的作用很简单,当前帧绘制完后执行 addPostFrameCallback 的回调函数,这么说可能有点抽象,我具体展开聊聊。

使用场景

Flutter 中的界面组件(控件)只要一帧就能绘制渲染在屏幕上,当然,这一帧 Flutter 做了很多事,包括 Build、Layout 和 Painting 阶段。而 addPostFrameCallback 就是在每一帧绘制完成后再回调执行一些自己的方法。这个机制的使用场景非常多。

比如组件渲染完后做一些操作,像开启动画、弹出对话框 Dialog、获取组件 Widget 的大小和位置。或者使用 addPostFrameCallback 延迟加载数据,确保界面渲染完才加载数据,避免出现 UI 阻塞。还有,在界面组件渲染完成后,请求接口获取数据,动态添加组件等等。总之,当你需要在组件首次渲染完成后执行某些操作时,都可以使用它

如何使用

最常见就是在生命周期 init() 初始化中使用,因为 init() 只会在组件首次渲染执行,是很特殊的函数,而在 initState 中使用 WidgetsBinding.instance.addPostFrameCallback ,也就说明我们在组件首次渲染完成后执行回调函数。

 @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      print("initState: Frame has been rendered");
    });
  }

我们在 initState 中注册 WidgetsBinding.instance.addPostFrameCallback ,这个注册操作是在方法 initState 中执行的,但回调函数本身将在当前帧的绘制完成执行

其次我们还能在 build 方法中的使用 addPostFrameCallback 。这表明我们的回调函数会在每次 Widget 重新构建时执行,回调函数会多次渲染执行,而不是像 init() 中的只执行一次。

我这里举个例子,像 setState 会触发 build 方法,如果我们在 build 中使用 addPostFrameCallback ,这样每次 build 后都会执行回调函数。

class _FrameCallbackPageState extends State<FrameCallbackPage> {

  int _counter = 0;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      print("initState: Frame has been rendered");
    });
  }

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      print("setState: Frame has been rendered");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('WidgetsBinding Example')),
      body: Center(
        child: Text("Counter:$_counter")
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

上面代码运行后再点击按钮,打印日志:

flutter: initState: Frame has been rendered
flutter: setState: Frame has been rendered
flutter: setState: Frame has been rendered

OK,希望以上分享能帮到你。

本文由老郭种树原创,转载请注明:https://guozh.net/add-post-frame-callback/

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注