LoginSignup
14
7

More than 3 years have passed since last update.

Flutter:StatelessWidgetとStatefulWidgetの違い

Last updated at Posted at 2020-08-23

これは何か

StatelessWidgetStatefulWidget の違いをメモしたもの。
間違った理解や補足があればコメントしていただけると嬉しいです。

違い

先にまとめます。

StatelessWidget

  • 状態を持たない静的なWidget
    • データが一切変わらない
      • 例:アイコン、ラベル、テキスト...

StatefulWidget

  • 状態を持つ動的なWidget
    • ユーザーのインタラクションによってデータが変わる
      • 例:チェックボックス、フォーム、スライダー...

画像で見た方が理解しやすいかも。
image.png

具体例

コードを読みながら違いを見てみる。
以下は、Flutterの初期プロジェクトで使われるカウンターアプリのコードです。
image.png

main.dart
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {

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

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

  final String title;

  @override
  _MyHomePageState 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>[
            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),
      ),
    );
  }
}

StatelessWidget

まずは StatelessWidget の部分を見る。

main.dart
class MyApp extends StatelessWidget {

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

ここはビルドされると、return文以下が実行されるだけで、それ以降は外部からの(ユーザーのインタラクション等)影響を受けない。
つまり一度画面が描画されると、あとから再描画されることはなく状態も変わらない。
そして、状態が変わる部分を MyHomePage に切り分けていることが分かる。

StatefulWidget

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

  final String title;

  @override
  _MyHomePageState 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>[
            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),
      ),
    );
  }
}

ここはビルドされ、一度画面の描画が終わっても、ユーザーのインタラクションによってデータが変わる(画面が再描画される)箇所がある。
その起点が、画面下部にあるfloatingActionButton
1. onPressed(ボタンを押す)によって
2. _incrementCounter(カウンター数を増やすメソッド)が呼ばれ
3. setState(状態を保持するメソッド)によって再度画面が描画されて
4. _counter++(カウンター数を繰り上げるメソッド)によって1を足している。
このように最初はカウンター数を0と定義していたものを、ユーザーのインタラクションによって状態が変更していることが分かる。
これが状態を持つ動的なStatefulWidgetである。

その他個人的な学び

'$_counter'という書き方をすることで、number型をstring型に変えられる。
詳細:https://dart.dev/guides/language/language-tour#a-basic-dart-program

参考

14
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
7