flutter开发实战-第一帧布局完成回调实现

flutter开发实战-第一帧布局完成回调实现

在开发中,我们有时候需要在第一帧布局完成后调用一些相关的方法。这里记录一下是实现过程。

Flutter中有多种不同的Binding,每种Binding都负责不同的功能。下面是Flutter中常见的Binding:

这里简单说明一下WidgetsBinding

一、WidgetsBinding

WidgetsBinding:负责管理Flutter应用程序的生命周期,包括启动、暂停、恢复和停止等。

WidgetsBinding它用于监听用户设置的更改,如语言的修改。 不仅如此, WidgetsBinding 否是 Widgets 与 Flutter 引擎之间通信的桥梁,有两个主要的功能:

* 1 负责处理Widgets结构变更的过程;

* 2 第二个是触发渲染事件。

一些小组件的结构更改是 BuildOwner 来完成的,它跟踪需要重建的小部件,并处理应用于整个小部件结构的其他任务。

二、实现第一帧布局完成后调用相关方法

在WidgetsBinding中,我们可以看到endOfFrame方法,源码如下

复制代码
/// Returns a Future that completes after the frame completes.
  ///
  /// If this is called between frames, a frame is immediately scheduled if
  /// necessary. If this is called during a frame, the Future completes after
  /// the current frame.
  ///
  /// If the device's screen is currently turned off, this may wait a very long
  /// time, since frames are not scheduled while the device's screen is turned
  /// off.
  Future<void> get endOfFrame {
    if (_nextFrameCompleter == null) {
      if (schedulerPhase == SchedulerPhase.idle) {
        scheduleFrame();
      }
      _nextFrameCompleter = Completer<void>();
      addPostFrameCallback((Duration timeStamp) {
        _nextFrameCompleter!.complete();
        _nextFrameCompleter = null;
      });
    }
    return _nextFrameCompleter!.future;
  }

方法中描述如下

复制代码
该方法返回在帧完成后完成的Future。
如果在帧之前调用的时候,则会立即调度帧。如果在帧期间调用此操作,则Future将在当前帧完成后调用。
如果设备的屏幕当前已关闭,这可能会等待很长时间。

所以我们需要在initState中调用相关方法

复制代码
WidgetsBinding.instance.endOfFrame.then(
          (value) {
        if (mounted) {
           // TODO调用相关方法
        }
      },
    );

实现第一帧布局完成后调用完成代码如下

复制代码
class AfterLayoutPage extends StatefulWidget {
  const AfterLayoutPage({super.key});

  @override
  State<AfterLayoutPage> createState() => _AfterLayoutPageState();
}

class _AfterLayoutPageState extends State<AfterLayoutPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('AfterLayoutPage'),
      ),
      body: Container(
        color: Colors.blueGrey,
      ),
    );
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    WidgetsBinding.instance.endOfFrame.then(
          (value) {
        if (mounted) {
          showHelloWorld();
        }
      },
    );
  }

  void showHelloWorld() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          content: const Text('Hello World'),
          actions: <Widget>[
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: const Text('DISMISS'),
            )
          ],
        );
      },
    );
  }
}

可以将该实现包装成一个Mixin

复制代码
import 'dart:async';

import 'package:flutter/widgets.dart';

mixin AfterLayoutMixin<T extends StatefulWidget> on State<T> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.endOfFrame.then(
      (_) {
        if (mounted) afterFirstLayout(context);
      },
    );
  }

  FutureOr<void> afterFirstLayout(BuildContext context);
}

调整后代码如下

复制代码
class AfterLayoutPage extends StatefulWidget {
  const AfterLayoutPage({super.key});

  @override
  State<AfterLayoutPage> createState() => _AfterLayoutPageState();
}

class _AfterLayoutPageState extends State<AfterLayoutPage> with AfterLayoutMixin<AfterLayoutPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('AfterLayoutPage'),
      ),
      body: Container(
        color: Colors.blueGrey,
      ),
    );
  }

  @override
  void afterFirstLayout(BuildContext context) {
    // Calling the same function "after layout" to resolve the issue.
    showHelloWorld();
  }

  void showHelloWorld() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          content: const Text('Hello World'),
          actions: <Widget>[
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: const Text('DISMISS'),
            )
          ],
        );
      },
    );
  }
}

三、小结

flutter开发实战-第一帧布局完成回调实现

学习记录,每天不停进步。

相关推荐
Xudde.2 小时前
班级作业笔记报告0x04
笔记·学习·安全·web安全·php
zzh0815 小时前
MySQL高可用集群笔记
数据库·笔记·mysql
绛橘色的日落(。・∀・)ノ5 小时前
Matplotlib实践学习笔记
笔记·学习
chase。5 小时前
【学习笔记】AGILE:把人形机器人强化学习从“玄学”变成“工程学”
笔记·学习·敏捷流程
久菜盒子工作室5 小时前
高等教育学|第一章高等教育概述
经验分享·笔记·课程设计
tq10866 小时前
语言流形与思维共生:中西认知图景的差异与交融
笔记
YuanDaima20486 小时前
基于 LangChain 1.0 的检索增强生成(RAG)实战
人工智能·笔记·python·langchain·个人开发·langgraph
_李小白6 小时前
【OSG学习笔记】Day 31: 渲染到纹理(RTT)
笔记·数码相机·学习
2501_920627618 小时前
Flutter 框架跨平台鸿蒙开发 - 派对策划助手应用
flutter·华为·harmonyos
练习时长一年8 小时前
我的开发笔记
笔记