🤔

Flutter Statefulウィジェットってなんだ

2021/09/08に公開

FlutterにおけるStatefulWidgetについて調べてみた

状態を持っている動的なウィジェット

本稿、あるいは本シリーズは公式ドキュメントを参考に、初学者が理解を深めるためのプログラミングノートです。

以前、FlutterにおけるStatelessWidgetについて学んだが、今回はStatefulWidgetについて理解していく。前回も確認したが、Stateとは日本語で状態を表す。StatelessWidgetが状態のない(例外を除き静的な)ウィジェットであり、StatefulWidgetは状態を持つ動的なウィジェットだ。

例としてFlutterのNewProjectのデフォルトのコードを紹介する。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  final String title;
  
  _MyHomePageState createState() => _MyHomePageState();
}

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

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

ここで初学者としては当然の疑問が浮かぶだろう。静的なUIと動的なUIとはなにか。その答えはFlutter入門アカデミーさまが紹介している記述がわかりやすかった。

Flutterで使用されているWidgetは全て「StatelessWidget」または「StatefulWidget」のどちらかに分類されます。StatelessWidgetとは状態がずっと変化しないWidgetのことを呼び、StatefulWidgetとはユーザーによる操作(インタラクション)やデータを受け取った際などに状態が変化する可能性のあるWidgetのことを呼びます。

Flutter入門アカデミー 【Flutter】StatelessWidgetとStatefulWidgetの違いと使い方 https://flutternyumon.com/flutter-statelesswidget-vs-statefulwidget/ 2021/09/08に引用

これにより、静的と動的の違いが分かっただけでなく、Flutterにはそのふた通りのUIしか存在しないという知識も得た。

上記コードで考えてみるとMyAppクラスはStatelessWidgetであるため、「状態がずっと変化しない Widget」ということになる。そして、MyHomePageクラスとそれを継承している_MyHomePageStateクラスは「値を受け取った際に状態が変化する可能性のあるWidget」ということになる。

ひとまず、StatefulWidgetの何となくの理解はできた。つまり、データを受け取ったときに状態を変化させるアプリを作る際に必要なWidgetである。

しかし、StatefulWidgetを適切に使用するためには複数の前提知識があることも事実だ。そのため、以下のような項目でStatefulWidgetについて調べ、別稿にまとめることにした。本稿はあくまでもStatefulWidgetの概要の理解だけにとどめておく。

・コンストラクタとはなにか

・superとはなにか

・createState()とはなにか

・State<>とはなにか

・setState()とはなにか

StatefulWidgetをきちんと理解するには実は前提知識がたくさん必要

以下、本来は本稿で理解しておきたかったが、複雑すぎるため記事を分けて考えることに決めた「key」について調べた途中経過である。

keyについて

気になるのは「Key? key」という記述、また「super」という記述だ。

StatefulWidgetはsetState()をトリガーに描画更新処理を行う。その際、更新前後(新旧)のKeyとクラス名を参照するようだ(参考資料)。

簡単に言うと、ElementからWidgetを識別するためのIDです。Keyは意図的に指定しないとデフォルトではnullです。

必要となるシーンが限定される感じですが、よく紹介されているのは以下ですね。
ただ、必要性が分かるようで分からない感じで、何となく使えている感じがします。

ToDoアプリのようなStateをもったWidget郡のソート, 追加, 削除
Listのスクロール位置の保存
本記事を最後まで読んで頂くと理解できると思いますが、Widgetツリーの中でノード (あるWidget) を他の場所に移動させる場合など、Widgetツリーと対になるElementツリー側から特定のWidgetを識別する必要がある場合にのみKeyを利用します。

@kurun_pan Flutter WidgetにKeyが必要な理由, 仕組みについて https://qiita.com/kurun_pan/items/f91228cf5c793ec3f3cc#keyが必要な理由と仕組みについて-1回目今回 2021/09/08に引用

つまり、そもそもKeyを設定していないと、更新前後の参照ができない(null)であるということらしい。しかし、様々調べてみるとこれらを理解するには、コンストラクタや名前付きメソッド、関数やメソッド呼び出しの際に名前付き引数を与えることができるというような、仕組みを理解していないと難しいと判断できた。そのため、keyについては別稿で詳細を追うことにする。

以上

Discussion