🤔

StatelessWidgetとStatefulWidgetって何が違うの?

2023/08/24に公開

始めまして!
このアカウントでは、Flutterを学習しているときに疑問に思ったことなどをお伝えしていこうと思います。
今回はStatelessWidgetとStatefulWidgetの違いについてです。

はじめに

Flutterを勉強していてStatelessWidgetとStatefullWidgetって何が違うの?となったので解説していきたいと思います。

Widgetとは?

StatelessWidgetとStatefullWidgetのどちらにもWidgetと書かれていますね。
FlutterではWidgetが使われますが、そもそもこのWidgetって何なんでしょうか🤔
FlutterではWidgetとはUI(画面の見た目の部分)を構築する際のパーツのことをWidgetと呼びます。
下の図で説明すると、
altテキスト

  • MyApp: 自分で作成したWidget
  • MaterialApp: マテリアルデザイン用Widget
  • Scaffold: マテリアルデザイン用Widget
  • AppBar: アプリケーションバー用Widget
  • Center: 中央寄せ用Widget
  • Text: テキスト用Widget
  • FloatingActionButton: アクションボタン用Widget

この画面は全てツリー状に組み合わさったWidgetで構成されています。
このように、FlutterでUIを構築するときには、たくさんのWidgetをツリー状に組み合わせることで、いろいろなUIを実現することができます。

Stateとは?

Widgetについては、アプリのUIを構築するためのものということが理解できたと思います。
続いては、こちらもどちらにも共通して書かれているStateについて解説していこうと思います。

Stateとは、日本語に翻訳すると状態と訳され、アプリ開発においてUIを更新するために必要なデータのことを指します。

下のデフォルトアプリの画面で説明すると、画面には0のデータを持った数字が描画されています。 

これをプラスボタンを押すことによって、0から1に変更されました。

この動きは、

  1. 0というState(状態)を持ったデータがあり
  2. プラスボタンを押すことで、なんらかのアクション(今回は1を足す)が発生し、
  3. その結果0のデータが1に変更し、1になったStateを描画する

ということになります。

このStateは、
- モーダルの開閉
- TwitterやInstagramのツイート更新

などアプリ開発において、多くのState(状態)を保持して、状態を応じてUIを変化させています。

StatelessWidgetとは

WidgetとStateについて理解ができたところで、まずStatelessWidgetについて見ていきましょう。
StatelessWidgetとは、状態(state)を持たない静的なWidgetのことです。
状態を持たないということは、何が画面上の値を変更したいと思っても、画面には再描画されません。
そのため、状態を保つ必要がないWidgetについては、StatelessWidgetを使用しましょう。
下のサンプルプログラムでは、状態を変更する必要がないtitleやアプリのテーマカラーなどについて定義したWidgetとなっています。

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

StatefullWidgetとは

Statefullwidgetは先ほどのStatelessWidgetと違い、State(状態)の変更を持つことができる動的なWidgetです。
上記のデフォルトアプリのように、データを更新させて再描画させたいときにはStatefullWidgetを使用しましょう。
下のプログラムでは、上記のデフォルトアプリであるプラスボタンを押すたびにTextWidgetの値を動的に変更させています。

class _MyHomePageState extends State<MyHomePage> {
 //Stateを持ったデータ
  int _counter = 0;

  void _incrementCounter() {
   //これがないと画面に再描画されません!!
    setState(() {
    //1を足す
      _counter++;
    });
  }

  @override
  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.display1,
            ),
          ],
        ),
      ),
      //プラスボタン
      floatingActionButton: FloatingActionButton(
      //プラスボタンを押したときに_incrementCounter関数を発火させる
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

ここでの注意点はデータを更新するときにはsetStateを使うところです。
setStateを忘れてしまうと、データは更新されますが、画面には再描画されないので注意が必要です。

まとめ

  • FlutterのUIはWidgetといったパーツを組み合わせることで構築している
  • Stateとは状態のことであり、UIを更新するために必要なデータのことである
  • StatelessWidgetとは、状態を持たない静的なWidgetであり、何が画面上の値を変更したいと思っても、画面には再描画できない
  • StatefullWidgetとはState(状態)の変更を持つことができる動的なWidgetであり、データを更新させて再描画させたいときにはStatefullWidgetを使用する

Discussion