Flutter:ウィジェットビルドでメソッドを実行します


133

ウィジェットのビルド/ロードが完了したら関数を実行できるようにしたいのですが、方法がわかりません。私の現在の使用例は、ユーザーが認証されているかどうかを確認し、認証されていない場合はログインビューにリダイレクトすることです。ログインビューまたはメインビューのいずれかを前に確認してプッシュしたくありません。メインビューがロードされた後に実行する必要があります。これを行うために使用できるものはありますか?


でログインプロセスを開始することはほとんどありませんbuild。ビルドはいつでも複数回呼び出すことができます。
ギュンターZöchbauer

回答:


195

あなたが使うことができます

https://github.com/slightfoot/flutter_after_layout

レイアウトが完了した後、関数を1回だけ実行します。または、その実装を見て、コードに追加してください:-)

これは基本的に

  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => yourFunction(context));
  }

ありがとう@thomasあなたのansは私にとって非常に役に立ちます。私は2日前にこれに取り組み、今では彼らとあなたの回答を読んだ後です。もう一度ありがとうございました
RavindraBhanderi18年

8
anmol.majhail答え@を参照してください:WidgetsBinding.instance.addPostFrameCallback((_) => yourFunciton(context));もはや機能していません
パブロ・インスア

こんにちは@Thomas、それは私のために働いていません。それでもnull例外が発生します。何か案が ?
zukijuki

1
@anunixercoder:ユースケースによって異なります。時々、あなたはそれをinitState例えば以外で呼ぶべきです。でbuild
Giraldi

2
メソッドsetState内を呼び出しyourFunctionて機能させる必要があります
Pars

92

更新: Flutter v1.8.4

上記の両方のコードが機能しています。

ワーキング:

WidgetsBinding.instance
        .addPostFrameCallback((_) => yourFunction(context));

ワーキング

import 'package:flutter/scheduler.dart';

SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));

1
2番目のものはもう機能しません。NoSuchMethodError (NoSuchMethodError: The method 'addPostFrameCallback' was called on null. Receiver: null
オリバーディクソン

1
@ EliaWeiss-ユースケースによって異なります-これは、ビルド後にウィジェットで関数を呼び出す方法にすぎません。典型的な用途は、init()メソッドになります
anmol.majhail

21

3つの可能な方法があります:

1) WidgetsBinding.instance.addPostFrameCallback((_) => yourFunc(context));

2) Future.delayed(Duration.zero, () => yourFunc(context));

3) Timer.run(() => yourFunc(context));

についてはcontextScaffold.of(context)すべてのウィジェットがレンダリングされた後に使用するために必要でした。

しかし、私の謙虚な意見では、それを行うための最良の方法はこれです:

void main() async {
  WidgetsFlutterBinding.ensureInitialized(); //all widgets are rendered here
  await yourFunc();
  runApp( MyApp() );
}

14

Flutter1.2-ダーツ2.2

公式のガイドラインと情報源によると、レイアウトの最後のフレームも描画されたことを確認したい場合は、次のように書くことができます。

import 'package:flutter/scheduler.dart';

void initState() {
   super.initState();
   if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) {
        SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));
   }
}

私にとってこれはinitState()時点で私はschedulerPhaseを取得しているため、仕事しませんでしたSchedulerPhase.idleのそれは実際に働いていたどのような値...ビルド内でそのチェック()を追加しました
アレッシオ

11

ReactNativeにcomponentDidMount相当するものを探しているなら、Flutterがそれを持っています。それほど単純ではありませんが、同じように機能します。Flutterでは、Widgetsはイベントを直接処理しません。代わりに、Stateオブジェクトを使用してそれを行います。

class MyWidget extends StatefulWidget{

  @override
  State<StatefulWidget> createState() => MyState(this);

  Widget build(BuildContext context){...} //build layout here

  void onLoad(BuildContext context){...} //callback when layout build done
}

class MyState extends State<MyWidget>{

  MyWidget widget;

  MyState(this.widget);

  @override
  Widget build(BuildContext context) => widget.build(context);

  @override
  void initState() => widget.onLoad(context);
}

State.initState画面がレイアウトのレンダリングを終了すると、すぐに呼び出されます。また、デバッグモードの場合は、ホットリロードでも、明示的に呼び出す時間になるまで、呼び出されることはありません。


私の例では、StatefulWidgetクラスを使用してStateオブジェクトをと同じように処理できますが、StatelessWidget強くお勧めしません。私はまだ問題が見つかりましたが内部のすべてのものを実装してみてくださいませんよState最初のオブジェクトを
jerinho.com

2
flutter.dev/docs/cookbook/networking/fetch-data Googleは、initState()でデータフェッチを呼び出すことをお勧めします。したがって、このソリューションに問題はありません。実際、これは受け入れられた答えであるはずです。
開発者

React Nativeでは、componentWillMountレイアウトレンダリングの直前にデータフェッチを実行できます。Flutterはより簡単なソリューションを提供します。initState両方のデータフェッチのために十分であるとレイアウト上でレンダリング、我々はそれを正しく行うには方法を知っていれば
jerinho.com

1
componentWillMountはまもなく非推奨になります。したがって、フェッチは、コンポーネントがマウントおよび構築された後に実行されます。
開発者

10

Flutterバージョン1.14.6、Dartバージョン28。

以下は私のために働いたものです、あなたは単にビルドメソッドの後に起こりたいすべてを別のメソッドまたは関数にバンドルする必要があります。

@override
void initState() {
super.initState();
print('hello girl');

WidgetsBinding.instance
    .addPostFrameCallback((_) => afterLayoutWidgetBuild());

}

5

これを行うための最良の方法、

1.WidgetsBinding

WidgetsBinding.instance.addPostFrameCallback((_) {
      print("WidgetsBinding");
    });

2.WidgetsBinding

SchedulerBinding.instance.addPostFrameCallback((_) {
  print("SchedulerBinding");
});

内部initStateで呼び出すことができます。両方とも、ビルドウィジェットがレンダリングを行った後に一度だけ呼び出されます。

@override
  void initState() {
    // TODO: implement initState
    super.initState();
    print("initState");
    WidgetsBinding.instance.addPostFrameCallback((_) {
      print("WidgetsBinding");
    });
    SchedulerBinding.instance.addPostFrameCallback((_) {
      print("SchedulerBinding");
    });
  }

上記の両方のコードは、両方が同様のバインディングフレームワークを使用するため、同じように機能します。違いについては、以下のリンクを見つけてください。

https://medium.com/flutterworld/flutter-schedulerbinding-vs-widgetsbinding-149c71cb607f


3

SchedulerBindingを試してください。

 SchedulerBinding.instance
                .addPostFrameCallback((_) => setState(() {
              isDataFetched = true;
            }));

0

これを1回だけ実行する場合は、フレームワークがinitState()作成するStateオブジェクトごとにメソッドを1回だけ呼び出すため、これを実行します。

 @override
  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => executeAfterBuildComplete(context));
  }

戻るように何度もこれを実行したり、次の画面に移動したりするdidChangeDependencies()場合などは、このStateオブジェクトの依存関係が変更されたときに呼び出されるため実行します。

たとえば、前の呼び出しが後で変更されたをbuild参照したInheritedWidget場合、フレームワークはこのメソッドを呼び出して、このオブジェクトに変更について通知します。

このメソッドは、の直後にも呼び出されinitStateます。BuildContext.dependOnInheritedWidgetOfExactTypeこのメソッドから呼び出しても安全です。

 @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => executeAfterBuildComplete(context));
  }

これはあなたのコールバック関数です

executeAfterBuildComplete([BuildContext context]){
    print("Build Process Complete");
  }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.