Flutter開発実践 - フレームレイアウト完了コールバックの実装を優先

Flutter 開発の実践 - 最初のフレーム レイアウト完了コールバックの実装
ここに画像の説明を挿入します
開発中、最初のフレーム レイアウトが完了した後に、いくつかの関連メソッドを呼び出す必要がある場合があります。ここには実装プロセスが記録されます。

Flutter にはさまざまなバインディングがあり、それぞれのバインディングが異なる機能を担当します。Flutter の一般的なバインディングは次のとおりです。
ここでは WidgetsBinding について簡単に説明します。

一、ウィジェットバインディング

WidgetsBinding: 開始、一時停止、再開、停止など、Flutter アプリケーションのライフ サイクルの管理を担当します。
WidgetsBinding 言語の変更など、ユーザー設定の変更を監視するために使用されます。それだけではなく、WidgetsBinding は Widget と Flutter エンジンの間の通信のブリッジであり、2 つの主な機能があります:
  * 1 は Widget 構造の変更のプロセスを処理する責任を負います;
  * 2 2 つはレンダリング イベントをトリガーすることです。
一部のウィジェット構造変更は BuildOwner によって行われ、BuildOwner は再構築が必要なウィジェットを追跡し、ウィジェット構造全体に適用される他のタスクを処理します。

2. 最初のフレームレイアウトが完了したら、関連するメソッドを呼び出します。

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'),
            )
          ],
        );
      },
    );
  }
}

3. まとめ

Flutter開発実践 - フレームレイアウト完了コールバックの実装を優先

勉強して記録し、日々改善を続けてください。

おすすめ

転載: blog.csdn.net/gloryFlow/article/details/135127060