Flutterで画面(Widget)の初回表示時にのみ処理を実行する

2022.10.05

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部 IoT事業部の若槻です。

最近はじめたFlutterアプリ開発で、画面(Widget)の初回表示時にのみ任意の処理を実行したいケースがあったので、対応した内容を紹介します。

導入

サンプルとして、flutter create コマンドで作成したカウンターアプリを使用します。

下記は生成されたmain.dartで定義されたMyHomePage画面のコードです。(自動挿入されるコメントは省いています。)

lib/main.dart

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

Flutter(Dart)で画面(Widget)を実装する場合は、主にStatefulWidgetまたはStatelessWidgetを使用します。

それぞれの使い分けは名前の通りで、StatefulWidgetは状態(State)を持たせたいWidget、StatelessWidgetは静的なWidgetを作る際に使用します。

今回のサンプルのカウンターアプリではボタンクリックによるカウントアップを画面表示させるため、上記コードの通りStatefulWidgetが使われています。

initStateを使って初回のみ実行させる

さてこのStatefulWidgetの画面の初回表示時に任意の処理を実行したいです。

その場合はStatefulWidgetで利用可能なメソッドinitStateを使います。

_MyHomePageStateで次のようにinitStateで処理を記載します。

lib/main.dart

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  @override
  void initState() {
    print("MyHomePage画面が表示されました。");

    super.initState();
  }

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    //略
  }
}

StatefulWidgetではStateオブジェクトによるライフサイクル管理が行われ、initStateはWidgetの初期化時のみ呼び出されます。

flutter run -d chromeコマンドでアプリをWebで起動します。

するとPrint出力処理が行われました。

$ flutter run -d chrome
Launching lib/main.dart on Chrome in debug mode...
Waiting for connection from debug service on Chrome...             10.8s
This app is linked to the debug service: ws://127.0.0.1:58290/bXekE9NwhZU=/ws
Debug service listening on ws://127.0.0.1:58290/bXekE9NwhZU=/ws

 Running with sound null safety 

  To hot restart changes while running, press "r" or "R".
For a more detailed help message, press "h". To quit, press "q".

An Observatory debugger and profiler on Chrome is available at: http://127.0.0.1:58290/bXekE9NwhZU=
Flutter Web Bootstrap: Programmatic
MyHomePage画面が表示されました。
The Flutter DevTools debugger and profiler on Chrome is available at: http://127.0.0.1:9102?uri=http://127.0.0.1:58290/bXekE9NwhZU=

ボタンをクリックしてカウンターを増やしてみます。

コンソールには追加のPrint出力は表示されていません。ちゃんと初回画面表示時のみ処理を実行できています!

誤った方法

次のようにWidget build()内に記載した処理はステート変更毎に実行されるため、画面初回表示時のみ実行したい場合は誤った方法となります。

lib/main.dart

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    print('MyHomePage画面が表示されました。');
    //略
  }
}

flutter run -d chromeコマンドでアプリを起動し、ボタンクリックしてカウントアップを行います。

すると画面初回表示時に加えてボタンクリック毎に処理が実行されてしまいました。

$ flutter run -d chrome
Launching lib/main.dart on Chrome in debug mode...
Waiting for connection from debug service on Chrome...             10.5s
This app is linked to the debug service: ws://127.0.0.1:58600/9so_Ka2lQ9w=/ws
Debug service listening on ws://127.0.0.1:58600/9so_Ka2lQ9w=/ws

 Running with sound null safety 

  To hot restart changes while running, press "r" or "R".
For a more detailed help message, press "h". To quit, press "q".

An Observatory debugger and profiler on Chrome is available at: http://127.0.0.1:58600/9so_Ka2lQ9w=
Flutter Web Bootstrap: Programmatic
MyHomePage画面が表示されました。
The Flutter DevTools debugger and profiler on Chrome is available at: http://127.0.0.1:9102?uri=http://127.0.0.1:58600/9so_Ka2lQ9w=
MyHomePage画面が表示されました。
MyHomePage画面が表示されました。
MyHomePage画面が表示されました。
MyHomePage画面が表示されました。
MyHomePage画面が表示されました。

Flutterのライフサイクルの概念をよく分かっていない頃によくこれをやらかしました。

以上