文系プログラマーが語る

主にプログラミング関連の記事を書いています。

【Flutterで状態管理】StatelessWidgetとStatefulWidgetの違いと使い分け、InheritedWidgetについて(サンプルコードつき)

今回は、Flutterアプリの状態管理で大事なStatelessWidgetとStatefulWidgetの違いと使い分け、加えてInheritedWidgetについてまとめます。

 

この記事で分かること

✅StatelessWidgetとStatefulWidgetって何?
✅StatelessWidgetとStatefulWidgetの違いと使い分け
✅InheritedWidgetについて

 

目次

 

Flutterアプリの状態管理について

Flutterでの状態管理は基本として次に説明する「StatelessWidget」「StatefulWidget」があります。「状態管理」というのは「アプリの画面表示内容や内部データの管理」のことで、変化のある画面を作成したいときには必ず考えないといけないところです。

StatelessWidget

StatelessWidgetとは「自身の状態を持たない」ウィジェットのことで、例えば「アイコン」や「テキスト」、「タイトル」なんかが該当します。これらのウィジェットは一度作成されると"基本的には"その後変化することはありません。以下に例を示します。

※"基本的には"と書きましたがこれについては後程解説します。

サンプルコード
class Sample_Stateless extends StatelessWidget {
  const Sample_Stateless({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text("サンプル"),
        ),
        body: const Center(
            child: Text("サンプルテキスト"),
            )
        ),
      );
  }
}
実行画面

以上のような「状態の変化がない画面」を作成する際に用いるのが「StatelessWidget」です。

状態を保持するためには次に説明する「InheritedWidget」や「StatefulWidget」を用いる必要があります。

 

変化のある「StatelessWidget」??

先ほど「StatelessWidget」は"基本的には"画面の状態が変化することはないと書きました。これはどういうことでしょうか。実は、「StatelessWidget」であっても画面の状態が変化する場合があります。それは次に紹介する「InheritedWidget」を用いた場合です。

InheritedWidget

InheritedWidgetは、下位ツリーのウィジェットへのデータの受け渡しを外部から可能にするウィジェットです。先ほども述べたとおり、「StatelessWidget」は「自身の持つ」状態が変化しないウィジェットです。ですので、InheritedWidgetを用いて変数の値を外部(自身以外の場所)から変更することで画面の表示も変わり、「StatelessWidget」であっても動的な挙動をすることになります。

実際にはこの「InheritedWidget」を内包した「Riverpod」や「Provider」パッケージなどがよく利用されます。

詳しくは以下をご参照ください。
riverpod | Dart Package
プロバイダとは | Riverpod

 

StatefulWidget

次に、「StatefulWidget」についてです。これはStatelessWidgetとは対照的に「自身の状態が変化する可能性のある」ウィジェットです。例えば、「チェックボックス」や「テキストフィールド」などがあります。これらのウィジェットは、ユーザーの操作やデータの受け渡しによって画面の状態が変化することがあります。そしてその変化を保持する必要がある場合に、「StatefulWidget」は使用します。以下に例を示します。

サンプルコード
class Sample_Stateful extends StatefulWidget {
  const Sample_Stateful({super.key});

  @override
  State<Sample_Stateful> createState() => _Sample_Stateful();
}

class _Sample_Stateful extends State<Sample_Stateful>{
  String text = "";
  bool _isChecked = false;

  Widget build(BuildContext context){
    return Scaffold(
      appBar: AppBar(title: const Text('サンプル')),
      body: Center(
        child: Column(
          children: <Widget>[
          Checkbox(
          value: _isChecked,
          onChanged: (value) {
            setState(() {
              _isChecked = value!;
            });
          },
        ),
            ElevatedButton(
              onPressed: (){
                Navigator.push(context, MaterialPageRoute(builder: (context){
                  return Sample_Stateful_2();
                }),
                );
              },
              child: const Text('画面遷移'),
            )
          ]
        ),
      ),
    );
  }
}

class Sample_Stateful_2 extends StatelessWidget{
  Widget build(BuildContext context){
    return Scaffold(
      appBar: AppBar(title: const Text('サンプル_画面遷移後')),
      body: Center(
          child: ElevatedButton(
            onPressed: (){
              Navigator.pop(context);
            },
            child: const Text('戻る'),
          )
      ),
    );
  }
}
実行画面

 

これはチェックボックスにチェックを入れて画面遷移をし、戻ってきた際にチェックが保持されていることを示すサンプルです。

「StatefulWidget」の場合は、上の実行画面のように入力した内容が保持されている状態となります。

 

おわりに

今回はFlutterでの状態管理を行うためのウィジェット「StatelessWidge」「StatefulWidget」、加えて外部から状態管理を行うことができるウィジェットである「InheritedWidget」についてまとめました。この状態管理の考え方はより効率の良い、かつメンテナンス性の高いアプリを作ろうと思ったときに大事になってきます。この機会にぜひ理解を深めておきましょう!

以上となります、最後までお読みいただきありがとうございました!