1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【備忘録】Flutterの主要ウィジェットについて

Posted at

今後モバイルアプリ開発に関わる可能性があるため、代表的なウィジェットの特徴を簡潔にまとめてみました。

ウィジェット 状態管理 動的UI更新 シンプルさ パフォーマンス Providerの使用
StatelessWidget × × ×
StatefulWidget × ×
ConsumerWidget
StatefulConsumerWidget ×

1. StatelessWidget

状態を持たないウィジェット。ウィジェットの状態が変わらない場合に使用される。
静的なUI要素や、状態が外部から提供される場合に適している。

メリット
・シンプルで軽量
・状態管理が不要なため、コードが簡潔
・パフォーマンス〇
デメリット
・状態を持たないため、動的なUIの更新ができない

import 'package:flutter/material.dart';

class MyStatelessWidget extends StatelessWidget {
  final String title;

  MyStatelessWidget({required this.title});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Text('This is a StatelessWidget'),
      ),
    );
  }
}

2. StatefulWidget

内部に状態を持つウィジェット。状態が変化する場合に使用される。
動的に変化するUIに適している。

メリット:
・動的なUIの更新が可能
・状態管理がウィジェット内で完結する
デメリット:
・コードが複雑になる可能性がある
・パフォーマンス△

import 'package:flutter/material.dart';

class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int _counter = 0;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('StatefulWidget Example'),
      ),
      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),
      ),
    );
  }
}

3. ConsumerWidget

ConsumerWidgetは、Providerを使用して状態管理を行うウィジェット。
Providerから状態を取得し、UIを更新することができる。
メリット:
・Providerを使用することで、状態管理が容易
・状態の変更に応じて、必要な部分のみを再ビルドできる
デメリット:
・Providerの理解が必要

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

final counterProvider = StateProvider<int>((ref) => 0);

class MyConsumerWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final counter = ref.watch(counterProvider);

    return Scaffold(
      appBar: AppBar(
        title: Text('ConsumerWidget Example'),
      ),
      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: () => ref.read(counterProvider.notifier).state++,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

4. StatefulConsumerWidget

StatefulWidgetとConsumerWidgetの機能を組み合わせたウィジェット。
内部に状態を持ちながら、Providerからの状態も利用できる。
メリット
・内部状態と外部状態の両方を管理できる
・柔軟な状態管理が可能
デメリット:
・複雑な状態管理が必要なため、コードが複雑になる可能性がある
・Providerの理解とセットアップが必要

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

final counterProvider = StateProvider<int>((ref) => 0);

class MyStatefulConsumerWidget extends StatefulWidget {
  @override
  _MyStatefulConsumerWidgetState createState() => _MyStatefulConsumerWidgetState();
}

class _MyStatefulConsumerWidgetState extends State<MyStatefulConsumerWidget> {
  @override
  Widget build(BuildContext context) {
    return Consumer(
      builder: (context, ref, child) {
        final counter = ref.watch(counterProvider);

        return Scaffold(
          appBar: AppBar(
            title: Text('StatefulConsumerWidget Example'),
          ),
          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: () => ref.read(counterProvider.notifier).state++,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
        );
      },
    );
  }
}

まとめ

パフォーマンスを考えると、UI部分をStatelessWidgetで作成してデータ更新などで再描画が必要な部分のみConsumerWidgetを使用するのが一番よさそう

参考:
StatefulWidget & StatelessWidget
ConsumerWidget
StatefulConsumerWidget

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?