Flutter: Flutter入門と環境構築
Flutterを使えば、1つのDartコードベースでiOS、Android、Web、Desktopのアプリを構築できます — まるで1つのマスターキーで4つのドアを開けるように。
📋 前提条件: 事前の経験は不要です
1. このレッスンで学ぶこと
- FlutterフレームワークのアーキテクチャとDart言語との関係
- Widgetツリーのレンダリング原理(Everything is a Widget)
- Flutter 3.xの新機能:Impellerレンダリングエンジン、折りたたみ端末対応
- Windows/macOS/LinuxでのFlutter SDKのインストールとPATH設定
flutter create、flutter run、flutter doctorによるワークフローの確認
2. 起業家のリアルなストーリー
(1) 悩み:4つのプラットフォーム、4つのコードベース
Bobは起業家で、ShopAppというECプロジェクトをiOS、Android、Web、Desktopで同時に展開する必要があります。各プラットフォームに独自のネイティブコードベースが必要だと、4つの開発チームと4つのコードベースが必要になり、人件費は年間50万ドルを超えます。さらに、キャンペーンの立ち上げには要件定義から6週間かかります — 各チームが個別に実装しなければならないからです。
(2) Flutterのソリューション
Flutterは「一度書けば、どこでも動く」戦略を採用し、DartでUI層を記述し、独自の描画エンジンで直接ピクセルをレンダリングします。ネイティブUIコンポーネントには依存しません。
import 'package:flutter/material.dart';
// One codebase, four platforms
void main() => runApp(const ShopApp());
class ShopApp extends StatelessWidget {
const ShopApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ShopApp',
home: Scaffold(
appBar: AppBar(title: const Text('ShopApp')),
body: const Center(child: Text('Hello, Bob!')),
),
);
}
}
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
(3) 結果:1つのチームが4つを代替
Flutterを採用後、Bobの1つのチームが1つのコードベースを保守し、4つのプラットフォームで同時にリリースできるようになりました。キャンペーンの期間は6週間から1週間に短縮され、年間開発コストは50万ドルから15万ドルに削減されました。
3. Flutterの技術アーキテクチャ
Flutterはレイヤー化されたアーキテクチャを採用しており、上位のFrameworkから下位のEngineまで、それぞれが独自の責務を持ちます。
graph TD
A[Flutter SDK] --> B[Dart SDK]
A --> C[Framework Layer]
A --> D[Engine Layer]
C --> E[Material Library]
C --> F[Cupertino Library]
D --> G[Skia / Impeller]
D --> H[Platform Embedder]
H --> I[Android]
H --> J[iOS]
H --> K[Web]
H --> L[Windows/macOS/Linux]
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
(1) Frameworkレイヤー
Frameworkレイヤーは開発者が直接操作する部分で、すべてDartで書かれています:
- Widgetレイヤー:宣言的UIの記述(StatelessWidget / StatefulWidget)
- Elementレイヤー:Widgetのインスタンス化オブジェクト、ツリー構造の管理
- RenderObjectレイヤー:測定、レイアウト、描画を担当
| レイヤー | 責務 | 言語 |
|---|---|---|
| Widget | UI設定の宣言 | Dart |
| Element | Widgetツリーの差分管理 | Dart |
| RenderObject | レイアウトと描画 | Dart |
| Engine | レンダリングとI/O | C++ |
(2) Engineレイヤー
EngineレイヤーはC++で書かれており、主要コンポーネントは以下の通りです:
- Skia / Impeller:2Dグラフィックスレンダリングエンジン、DartのUI命令をGPU命令に変換
- Dart Runtime:JIT(開発時)とAOT(リリース時)のコンパイル
- Platform Embedder:プラットフォーム固有の組み込みレイヤー、イベントループとスレッドの管理
(3) Platform Embedder
各プラットフォームには異なるEmbedderの実装があり、以下を担当します:
| プラットフォーム | Embedder | レンダリング方式 |
|---|---|---|
| Android | flutter_shell (Java/Kotlin) |
GPU (Vulkan/OpenGL) |
| iOS | FlutterViewController (Swift/ObjC) |
GPU (Metal) |
| Web | HTML Canvas / WebGL | CanvasKit / HTML renderer |
| Desktop | GLFW / Win32 / Cocoa | GPU |
4. Everything is a Widget
Flutterの中核哲学:すべてはWidgetです。ボタン、フォント、スペーシング、さらにはレイアウトの制約もすべてWidgetです。
(1) Widgetの分類
| 種類 | 説明 | 例 |
|---|---|---|
| StatelessWidget | 不変、一度だけビルド | Text, Icon, Image |
| StatefulWidget | 可変状態、再ビルド可能 | TextField, Checkbox |
| RenderObjectWidget | レイアウトと描画を制御 | Flex, Stack, Positioned |
| ProxyWidget | サブツリーにデータを渡す | InheritedWidget, Provider |
▶ サンプル
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
: StatelessWidgetの商品カード
import 'package:flutter/material.dart';
class ProductCard extends StatelessWidget {
final String name;
final double price;
const ProductCard({
super.key,
required this.name,
required this.price,
});
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(name, style: const TextStyle(fontSize: 18)),
Text('\$${price.toStringAsFixed(2)}',
style: const TextStyle(color: Colors.green, fontSize: 16)),
],
),
),
);
}
}
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
▶ サンプル
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
: StatefulWidgetのカウンター
import 'package:flutter/material.dart';
class QuantitySelector extends StatefulWidget {
const QuantitySelector({super.key});
@override
State<QuantitySelector> createState() => _QuantitySelectorState();
}
class _QuantitySelectorState extends State<QuantitySelector> {
int _count = 1;
@override
Widget build(BuildContext context) {
return Row(
children: [
IconButton(
icon: const Icon(Icons.remove),
onPressed: () => setState(() => _count = (_count - 1).clamp(1, 99)),
),
Text('$_count', style: const TextStyle(fontSize: 20)),
IconButton(
icon: const Icon(Icons.add),
onPressed: () => setState(() => _count++),
),
],
);
}
}
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
5. 環境構築
(1) Flutter SDKのインストール
| 手順 | Windows | macOS | Linux |
|---|---|---|---|
| SDKのダウンロード | flutter.dev/docs/get-started/install/windows | flutter.dev/docs/get-started/install/macos | flutter.dev/docs/get-started/install/linux |
| 展開パス | C:\flutter |
~/development/flutter |
~/development/flutter |
| PATH設定 | システム環境変数に追加 | ~/.zshrcに追加 |
~/.bashrcに追加 |
▶ サンプル
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
: PATH設定(macOS/Linux)
# Add Flutter to PATH in ~/.zshrc or ~/.bashrc
export PATH="$HOME/development/flutter/bin:$PATH"
# Verify installation
flutter --version
# Output: Flutter 3.x.x • channel stable
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
▶ サンプル
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
: flutter doctorによる確認
# Run doctor to check all dependencies
flutter doctor
# Expected output:
# [✓] Flutter (Channel stable, 3.x.x)
# [✓] Android toolchain
# [✓] Chrome - develop for the web
# [✓] Android Studio
# [!] VS Code (install Flutter extension)
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
(2) IDEの設定
| IDE | 必須プラグイン | 推奨プラグイン |
|---|---|---|
| VS Code | Flutter, Dart | Flutter Widget Snippets, Error Lens |
| Android Studio | Flutter, Dart | Flutter Intl, Riverpod Snippet |
▶ サンプル
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
: 最初のプロジェクトを作成
# Create a new Flutter project
flutter create shop_app
# Navigate to project directory
cd shop_app
# Run on connected device or emulator
flutter run
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
6. 最初のHello World
▶ サンプル
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
: ShopApp Hello World
import 'package:flutter/material.dart';
void main() {
runApp(const ShopApp());
}
class ShopApp extends StatelessWidget {
const ShopApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'ShopApp',
theme: ThemeData(
colorSchemeSeed: Colors.blue,
useMaterial3: true,
),
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('ShopApp')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.shopping_bag, size: 80, color: Colors.blue),
const SizedBox(height: 16),
const Text('Welcome to ShopApp!',
style: TextStyle(fontSize: 24)),
const SizedBox(height: 8),
Text('Million-level products, USD settlement',
style: TextStyle(fontSize: 14, color: Colors.grey[600])),
const SizedBox(height: 24),
ElevatedButton(
onPressed: () {},
child: const Text('Start Shopping'),
),
],
),
),
);
}
}
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
▶ サンプル
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
: ホットリロードの体験
# Start app with hot reload support
flutter run
# After modifying code, press:
# r - Hot reload (keep state, update UI)
# R - Hot restart (reset state, rebuild)
# q - Quit
# Hot reload updates UI in <1 second
# Try: change 'Welcome to ShopApp!' to 'Hello Bob!'
# Press r → UI updates instantly
> **出力:** Flutter SDK(Flutter 3.x / Dart 3.x)でローカルに実行してください。PistonサーバーにはFlutterがインストールされていません。ローカルマシンで`flutter run`を使用して比較してください。実際のUI/状態はプラットフォームにより多少異なる場合があります。
7. Flutter 3.xの新機能
| 機能 | 説明 | 影響 |
|---|---|---|
| Impellerエンジン | プリコンパイル済みシェーダー、初回フレームのカクつきを解消 | レンダリング性能30%以上向上 |
| 折りたたみ端末対応 | 折りたたみ画面向けのアダプティブレイアウト | 対応デバイスの拡大 |
| Material 3 | 新しいデザイン仕様、ダイナミックカラー | よりモダンなUI |
| macOS / Linux安定版 | 公式Desktopプラットフォームサポート | 4プラットフォーム完全対応 |
| レンダリングエンジン | 初回フレーム時間 | シェーダーコンパイル | 対象バージョン |
|---|---|---|---|
| Skia | 200-500ms | 実行時JITコンパイル | Flutter 2.x |
| Impeller | <50ms | ビルド時AOTコンパイル | Flutter 3.x |
❓ よくある質問
flutter doctorが「Android licenses not accepted」と表示される場合?flutter doctor --android-licensesを実行し、各ライセンスを順に承認してください。📖 まとめ
- FlutterはFramework + Engineのレイヤーアーキテクチャ:FrameworkはDart、EngineはC++
- Everything is a Widget:StatelessWidget(不変)とStatefulWidget(可変)
- 環境構築は3ステップ:SDKのインストール → PATH設定 →
flutter doctorの実行 flutter createでプロジェクト作成、flutter runでデバッグ開始、ホットリロードで1秒未満の更新- Flutter 3.xのImpellerエンジンが初回フレームのカクつきを解消、Material 3がモダンなデザインを提供
📝 練習問題
- 基本(難易度 ⭐): コンピュータにFlutter SDKをインストールし、
flutter doctorを実行して、少なくとも4項目が合格することを確認してください。 - 中級(難易度 ⭐⭐): Hello Worldの例を修正し、現在の日付を表示するTextウィジェットを追加してください。
- チャレンジ(難易度 ⭐⭐⭐): 3つの商品カードを持つColumnを作成し、各カードに商品名とドル価格を表示してください。カードをクリックするとSnackBarで商品情報を表示するようにしてください。
← 前へ | 次へ →