モバイル開発におけるFlutter:概要、主要概念、動作の仕組み

著者: IT Sectr 公開日: 2026-07-09 読了時間: 11 分

Flutterは、ネイティブクロスプラットフォームアプリケーション向けのGoogle製UIフレームワークです。Flutter Docs (2025)によると、FlutterはGoogle Playで50万以上のアプリに使用されています。Widget、StatefulWidget、BuildContext、レンダリングツリーの理解はFlutter開発の基礎です。

重要ポイント

  • Widget — 基本的な構成要素。StatelessWidget(不変)vs StatefulWidget(setState()で可変)。
  • 3つのツリー:Widget Tree(設定)、Element Tree(要素)、RenderObject Tree(レンダリング)。
  • BuildContext — InheritedWidgetへのアクセス:Theme、MediaQuery、Navigator。InheritedWidget — データを下位に渡す。
  • Navigator — 画面スタック(Routes)。Navigator 2.0(Router) — 宣言的ナビゲーション。
  • Hot Reload — 1〜2秒で変更を注入。状態を保持。Hot Restart — 完全再起動。

Flutter:Widget、StatelessWidget、StatefulWidgetの基礎

Widget — UIの一部の宣言的な記述。FlutterのすべてはWidgetです:ボタンからアプリ自体まで。Widgetは設定です(UIそのものではありません)。StatelessWidget — 不変のWidget。build()は一度だけ呼び出されます。状態を持ちません。静的コンテンツに使用されます。StatefulWidget — 可変のWidget。変更可能なStateオブジェクトを持ちます。setState() — 再構築をトリガーします。State — StatefulWidgetに紐づく可変オブジェクト。変更可能なデータを含みます。

StatelessWidget vs StatefulWidget

StatelessWidget — build()は一度だけ呼び出されます。ヘッダー、アイコン、静的テキストに適しています。StatefulWidget — build()はsetState()が呼び出されるたびに実行されます。フォーム、変更のあるリスト、タイマーに適しています。InheritedWidget — コンストラクタを介さずにデータをツリーの下位に渡します。Theme、MediaQuery、Navigator — InheritedWidgetです。BuildContext — ツリー内のWidgetの位置。context.of<T>、context.watch<T>、context.select<T,R> — InheritedWidgetへのアクセス。

dart
// Flutter Widgetの例: setStateを使用するStatefulWidget
class CounterWidget extends StatefulWidget {
  const CounterWidget({Key? key}) : super(key: key);

  @override
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter Counter')),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('You have pushed the button:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _increment,
        child: const Icon(Icons.add),
      ),
    );
  }
}

Widget — 設定。StatelessWidget — 不変。StatefulWidget — setState()で可変。IT SectrはStatelessWidgetから始め、状態が必要な場合のみStatefulWidgetに切り替えることを推奨します。

ツリー(Widget Tree、Element Tree、RenderObject Tree)

Flutterは効率的なレンダリングのために3つのツリーを使用します。Widget Tree — 設定ツリー。Widgetは頻繁に作成されます(ビルドごと)、軽量です。Element Tree — 要素ツリー。Widgetごとに1つの要素(タイプが変わらない場合)。Element — WidgetとRenderObjectの間のブリッジ。RenderObject Tree — レンダリングツリー。サイズ、位置、描画を処理します。RenderObject — 重く、作成は稀です。FlutterはWidget Treeを比較してElement Treeを更新し、RenderObject Treeの更新をトリガーします。

KeysとElement Tree

Key — Element Tree内のWidget識別子。ValueKeyObjectKeyUniqueKeyPageStorageKey。KeyによりFlutterは再構築時に古いWidgetと新しいWidgetを対応付けられます。Keyがない場合、FlutterはWidgetのタイプと位置で対応付けます。GlobalKey — 別のWidgetからStateにアクセス。使用例:複雑なフォーム、アニメーション、テストでのStateアクセス。IT Sectrはリスト(List.generate)にはKeyを使用し、不要なGlobalKeyは避けることを推奨します。

Expanded — Row/Column/Flexで利用可能なスペースを埋めるWidget。Flexible — 埋めることを強制しません(小さくできます)。MediaQuery — デバイス情報を含むInheritedWidget:画面サイズ、向き、プラットフォーム、テキストスケール係数。Theme/ThemeData — 集中管理されたテーマ。Theme.of(context) — アクセス。MaterialApp — ルーティング、テーマ、ロケール設定のルートWidget。Scaffold — AppBar、Drawer、BottomNavigationBarを含む基本レイアウト。AppBar — 上部パネル。

Navigator — ルートスタック(Routes)。Navigator.push — 画面を開く(Futureを返す)。Navigator.pop — 閉じる(結果付き)。MaterialPageRoute — アニメーション遷移(右からスライド)。Named Routes — 文字列識別子。onGenerateRoute — 集中管理ハンドラー。Navigator 2.0(Router + RouteInformationParser + RouterDelegate) — ウェブ、ディープリンク、複雑なシナリオのための宣言的ナビゲーション。

Navigator 2.0 — 宣言的ナビゲーション。Router — 中央Widget。RouteInformationParser — URL解析。RouterDelegate — スタック管理。GoRouter(パッケージ) — Navigator 2.0の簡略化ラッパー。サポート:名前付きルート、パラメータ、リダイレクト、ディープリンク。IT SectrはほとんどのプロジェクトでGoRouterを、複雑なシナリオ(ウェブ、デスクトップ)でのみNavigator 2.0を推奨します。

非同期(FutureBuilder、StreamBuilder)

FutureBuilder — Futureに基づいてUIを構築するWidget。connectionState:none、waiting、active、done。使用例:HTTPリクエスト、DB読み取り、タイマー。StreamBuilder — Stream用Widget(無限データフロー)。snapshot.data、snapshot.hasError、snapshot.hasData。使用例:WebSocket、Firebase、位置情報更新。両Widgetは新しいデータを受信すると再構築されます。

状態管理

Provider — シンプルなDI+状態管理。ChangeNotifierProvider、MultiProvider。Riverpod — Providerの現代的代替:コンパイルセーフ、BuildContextに依存しない。Bloc — イベント駆動アーキテクチャ:Cubit(単純イベント)vs Bloc(複雑)。GetX — 軽量な状態管理+DI+ルーティング。setState — 最もシンプル、ローカル状態向け。IT Sectrは新規プロジェクトにRiverpod、既存プロジェクトにProviderを推奨します。

テーマと適応(MediaQuery、ThemeData)

MediaQuery — 画面サイズ、向き、プラットフォーム、textScaleFactor。MediaQuery.of(context).size.width。ThemeData — アプリのテーマ:色、フォント、形状。Theme.of(context).textTheme.bodyLarge。Hot Reload — 実行中のアプリへのコード注入。状態を保持。非サポート:main()の変更、グローバル変数、静的フィールド。Hot Restart — アプリの完全再起動(状態喪失)。Hot Reload — Flutterの開発者にとっての最大の利点。

Widgetタイプ 説明
StatelessWidget不変、buildは1回Text, Icon, Padding, Center
StatefulWidget可変、setStateで再構築TextField, Checkbox, AnimationController
InheritedWidgetデータを下位に渡すTheme, MediaQuery, Navigator
ProxyWidget他のWidgetのラッパーParentDataWidget (Positioned, Expanded)
RenderObjectWidgetRenderObjectを作成Column, Row, Stack(カスタム)

StatelessWidget — 静的コンテンツに。StatefulWidget — 動的コンテンツに。InheritedWidget — DIに。IT SectrはデフォルトでStatelessWidgetを、必要な場合のみStatefulWidgetを推奨します。

レスポンシブレイアウト

LayoutBuilder — 親の寸法に適応。OrientationBuilder — 向きに適応。Expanded vs Flexible — Row/Column内のスペース配分。MediaQuery — タブレットとデスクトップのブレークポイント。SafeArea — システム要素(ノッチ、ステータスバー)からのマージン。AspectRatio — 比率を維持。IT SectrはアダプティブレイアウトにLayoutBuilder、横向きにOrientationBuilderを推奨します。

テスト(Widget、Integration、Unit)

単体テスト — ビジネスロジック、リポジトリ、モデルのテスト。dart test — 実行。Widgetテスト — ウィジェットを隔離してテスト。WidgetTester — pumpWidget、tap、enterText。統合テスト — 実機/エミュレータでの完全シナリオ。Mockito — 依存関係のモック。Goldenテスト — スクリーンショット比較(goldenファイル)。IT Sectrは各画面にWidgetテスト、ビジネスロジックに単体テストを推奨します。

dart
void main() {
  testWidgets('Counter increments on tap', (tester) async {
    await tester.pumpWidget(const MaterialApp(home: CounterWidget()));

    expect(find.text('0'), findsOneWidget);

    await tester.tap(find.byType(FloatingActionButton));
    await tester.pump();

    expect(find.text('1'), findsOneWidget);
  });
}

アニメーション(暗黙的、明示的、Hero)

暗黙的アニメーション — AnimatedContainer、AnimatedOpacity、AnimatedPadding、TweenAnimationBuilder。プロパティ変更が自動的にアニメーション化。明示的アニメーション — Tween付きAnimationController。forward() / reverse()。Heroアニメーション — タグ付きHeroWidget — 画面間の遷移アニメーション。Staggeredアニメーション — Intervalを使ったアニメーションチェーン。Lottie — After Effectsアニメーションの統合。Rive — インタラクティブアニメーション(state machine)。IT Sectrは80%のケースでAnimatedContainer、複雑なシナリオでAnimationControllerを推奨します。

dart
class AnimatedBox extends StatefulWidget {
  @override
  State<AnimatedBox> createState() => _AnimatedBoxState();
}

class _AnimatedBoxState extends State<AnimatedBox> {
  bool _expanded = false;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => setState(() => _expanded = !_expanded),
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        width: _expanded ? 200 : 100,
        height: _expanded ? 200 : 100,
        color: _expanded ? Colors.blue : Colors.red,
        child: const Center(child: Text('Tap me')),
      ),
    );
  }
}

ネットワーキング(http、dio、graphql)

http — シンプルなHTTPクライアント(get、post、put、delete)。dio — インターセプター、タイムアウト、リトライ、ロギング付きの高度なクライアント。graphql_flutter — Flutter用GraphQLクライアント。json_serializable — アノテーションによるfromJson/toJson生成。Retrofit Dart — Retrofitのようなtype-safe HTTPクライアント。WebSocket — web_socket_channel経由。Firebase — Cloud Firestore、Realtime Database、Cloud Functions。IT SectrはREST APIにdio、GraphQLにgraphql_flutterを推奨します。

Flutter DevTools — ツールセット:Inspector(ウィジェットツリー)、Timeline(パフォーマンス)、Memory、Network、Logging。Profile mode — デバッグなしのプロファイリング。Performance overlay — FPS、ビルド時間。Flame chart — フレームチャートトレーシング。DevTools — 本番環境でのFlutterアプリケーション最適化に不可欠なツール。

Flutter Web — FlutterをWASM(WebAssembly)にコンパイル。CanvasKit(Skia)vs HTML renderer。CanvasKit — ピクセルパーフェクトだが重い。HTML renderer — 軽量だが制限あり。WASM(Flutter 3.22+) — ネイティブパフォーマンス。LayoutBuilderとMediaQueryによるレスポンシブ適応。IT SectrはデスクトップウェブアプリケーションにCanvasKit、コンテンツサイトにHTML rendererを推奨します。

よくある質問

StatelessWidgetとStatefulWidgetの違いは何ですか?

StatelessWidget — 不変、buildは1回。StatefulWidget — 可変なStateとsetState()を持つ。

Widget Tree、Element Tree、RenderObject Treeとは何ですか?

Widget Tree — 設定。Element Tree — ブリッジ。RenderObject Tree — レンダリング(サイズ、描画)。

BuildContextとInheritedWidgetとは何ですか?

BuildContext — ツリー内のWidget位置。InheritedWidget — データを下位に渡す(Theme、MediaQuery)。

FlutterでNavigatorとRouteはどのように動作しますか?

Navigator — 画面スタック。push() → pop()。Named Routes — 文字列名。Navigator 2.0 — 宣言的。

FlutterでHot Reloadはどのように動作しますか?

Hot Reload — 1〜2秒でコード注入、状態保持。Hot Restart — 完全再起動。

まとめ

  • Widget — すべてがWidget。StatelessWidget vs StatefulWidget — 基本的な二分法。
  • 3つのツリー:Widget → Element → RenderObject。Widget — 設定、RenderObject — レンダリング。
  • BuildContext + InheritedWidget — 明示的な受け渡しなしでTheme、MediaQuery、Navigatorにアクセス。
  • Navigator — 画面スタック。Navigator 2.0 — ウェブとディープリンクのための宣言的ナビゲーション。
  • FutureBuilder — Future用。StreamBuilder — Stream用(Firebase、WebSocket)。
  • MaterialApp + Scaffold — アプリの骨格。ThemeData — 集中管理テーマ。
  • Hot Reload — Flutterのキラーフィーチャー。状態を保持したまま秒単位のコード更新。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談