CheatSheet
日本語 icon日本語English iconEnglish
チートシートとはカンニングペーパーのことです。それが転じて、本来覚えることをまとめておいたものです。
要点をすぐに参照できるようにまとめてみました。

Flutter / Dart

エンジニアのためのWebチートシート

Flutter は Google が開発したクロスプラットフォームUIフレームワークで、Dart 言語を使用します。 1つのコードベースで iOS、Android、Web、デスクトップアプリを開発できます。 Dart の基本構文、Null Safety、クラス、非同期処理、Widget、レイアウト、ナビゲーション、状態管理などをチートシートにまとめました。

Dart 基本構文

変数と定数

  • var, final, const, 型推論, Null Safetyの基本です。

    // 変数宣言
    var name = 'Dart';          // 型推論
    String lang = 'Flutter';    // 明示的な型
    int age = 10;
    double pi = 3.14;
    bool isActive = true;
    
    // final / const
    final createdAt = DateTime.now(); // 実行時定数
    const maxRetry = 3;               // コンパイル時定数
    
    // 文字列
    var greeting = 'Hello, $name!';
    var calc = '合計: ${1 + 2}';
    var multi = '''
    複数行文字列
    ''';
    var raw = r'改行しない\n';
    
    // 主要メソッド
    'hello'.toUpperCase();           // 'HELLO'
    '  hello  '.trim();              // 'hello'
    'hello world'.split(' ');        // ['hello', 'world']
    'hello'.contains('ell');         // true
    'hello'.substring(1, 3);        // 'el'

Null Safety & 型操作

  • Null許容型、null合体演算子、型チェック・キャストです。

    // Null Safety (Dart 3.x)
    int a = 1;           // non-nullable
    int? b;              // nullable (デフォルト null)
    int c = b ?? 0;      // null合体演算子
    b ??= 5;             // bがnullの場合のみ代入
    
    // nullアクセス防止
    String? s = null;
    int len = s?.length ?? 0;
    
    // null assertion (確実にnullでない場合)
    int value = b!;
    
    // 型チェック・キャスト
    if (value is String) { /* ... */ }
    if (value is! int) { /* ... */ }
    var str = value as String;  // キャスト

基本型一覧

説明
int整数(64bit)
double倍精度浮動小数点
numint, double の親型
StringUTF-16文字列
booltrue / false
List<T>順序付きコレクション(配列)
Set<T>重複なしコレクション
Map<K,V>キーバリュー
dynamic動的型(型チェック無し)
Object全オブジェクトの基底型(null以外)
void値を返さない
Never正常に完了しない関数の戻り値型
Recordレコード型(Dart 3)

制御フロー & 関数

制御フロー & パターンマッチ

  • if/else, switch式, if-case, for/for-in です。Dart 3のパターンマッチを含みます。

    // 三項演算子
    var result = x > 0 ? 'positive' : 'negative';
    
    // switch式 (Dart 3.x)
    var message = switch (status) {
      200 => 'OK',
      404 => 'Not Found',
      500 => 'Server Error',
      _ => 'Unknown',
    };
    
    // switch + パターンマッチ
    switch (value) {
      case int n when n > 0:
        print('正の整数: $n');
      case String s:
        print('文字列: $s');
      case (int x, int y):
        print('座標: ($x, $y)');
      default:
        print('その他');
    }
    
    // if-case (Dart 3.x)
    if (json case {'name': String name, 'age': int age}) {
      print('$name ($age)');
    }
    
    // for / for-in
    for (var i = 0; i < 5; i++) { /* ... */ }
    for (var item in list) { /* ... */ }

関数定義

  • アロー構文, 名前付き/位置パラメータ, クロージャ, typedefです。

    // アロー構文
    int add(int a, int b) => a + b;
    
    // 名前付きパラメータ
    String greet(String name,
        {required int age, String? title}) {
      return '${title ?? "Mr."} $name ($age)';
    }
    greet('Taro', age: 25);
    
    // オプショナル位置パラメータ
    String say(String msg,
        [String? from, String device = 'phone']) {
      return '$msg from ${from ?? "unknown"}';
    }
    
    // クロージャ / 高階関数
    var double = (int n) => n * 2;
    [1, 2, 3].map((e) => e * 2).toList();
    
    // typedef
    typedef IntOp = int Function(int, int);
    IntOp multiply = (a, b) => a * b;

Records(Dart 3)

  • 軽量なデータ構造と分割代入です。

    // Records (Dart 3.x)
    (String, int) userInfo() => ('Alice', 30);
    var (name, age) = userInfo(); // 分割代入
    
    // 名前付きフィールド
    ({String name, int age}) getUser() =>
        (name: 'Bob', age: 25);
    final (:name, :age) = getUser();
    
    // パターンマッチと組み合わせ
    var json = {'name': 'Alice', 'age': 30};
    if (json case {'name': String n, 'age': int a}) {
      print('$n is $a years old');
    }

クラス & OOP

クラス定義 & コンストラクタ

  • コンストラクタ省略記法, ファクトリ, ゲッター/セッターです。

    class User {
      final String name;
      int _age; // _ でプライベート
    
      // コンストラクタ省略記法
      User(this.name, this._age);
    
      // 名前付きコンストラクタ
      User.guest() : name = 'Guest', _age = 0;
    
      // ファクトリコンストラクタ
      factory User.fromJson(Map<String, dynamic> json) {
        return User(
          json['name'] as String,
          json['age'] as int,
        );
      }
    
      // ゲッター・セッター
      int get age => _age;
      set age(int value) {
        if (value >= 0) _age = value;
      }
    
      String greet() => 'Hi, I\'m $name';
    
      @override
      String toString() => 'User($name, $_age)';
    }

継承 & Mixin

  • extends, implements, with(Mixin), Extension Methodsです。

    // 継承
    class Admin extends User {
      final String role;
      Admin(super.name, super.age, this.role);
    
      @override
      String greet() => '${super.greet()} [Admin]';
    }
    
    // 抽象クラス
    abstract class Shape {
      double area();
    }
    
    // インターフェース(暗黙的)
    class Circle implements Shape {
      final double radius;
      Circle(this.radius);
      @override
      double area() => 3.14 * radius * radius;
    }
    
    // Mixin
    mixin Flyable {
      void fly() => print('Flying!');
    }
    class Duck extends Animal with Flyable {}
    
    // Extension Methods
    extension StringX on String {
      String get reversed =>
          split('').reversed.join('');
      bool get isEmail => contains('@');
    }
    print('hello'.reversed); // 'olleh'

クラス修飾子(Dart 3)& Enum

  • sealed, final, base, interface, Enhanced Enumです。

    // Dart 3.x クラス修飾子
    sealed class Result {}
    // 外部でextend/implement不可, 網羅チェック可
    
    final class Config {}
    // extend/implement完全禁止
    
    base class BaseService {}
    // implementのみ禁止(extend可)
    
    interface class Printable {}
    // extendのみ禁止(implement可)
    
    mixin class Validator {}
    // mixinとしてもclassとしても使える
    
    // Enhanced Enum (Dart 2.17+)
    enum Priority implements Comparable<Priority> {
      low(1, 'Low'),
      medium(2, 'Medium'),
      high(3, 'High');
    
      final int value;
      final String label;
      const Priority(this.value, this.label);
    
      @override
      int compareTo(Priority other) =>
          value - other.value;
    }

コレクション

List(配列)

  • 配列の操作、スプレッド演算子、コレクションif/forです。

    var list = [1, 2, 3];
    var typed = <String>['a', 'b', 'c'];
    
    // 操作
    list.add(4);
    list.addAll([5, 6]);
    list.remove(1);
    list.removeAt(0);
    list.insert(0, 10);
    list.contains(3);    // true
    list.indexOf(2);
    list.sublist(1, 3);
    list.sort();
    list.reversed.toList();
    list.first; list.last;
    
    // スプレッド演算子
    var extra = [0, ...list];
    var safe = [0, ...?nullableList];
    
    // コレクション if / for
    var items = [
      'always',
      if (isLoggedIn) 'profile',
      for (var i in list) 'item_$i',
    ];

Map & Set

  • キーバリュー、重複なしコレクション、主要メソッドです。

    // Set(重複なし)
    var set = {1, 2, 3};
    set.add(4);
    set.contains(2);          // true
    set.union({3, 4, 5});     // {1,2,3,4,5}
    set.intersection({2, 3}); // {2, 3}
    set.difference({2, 3});   // {1}
    
    // Map
    var map = {'name': 'Dart', 'version': 3};
    map['name'];               // 'Dart'
    map['newKey'] = 'value';
    map.containsKey('name');   // true
    map.remove('version');
    map.keys.toList();
    map.values.toList();
    map.entries.map(
      (e) => '${e.key}=${e.value}',
    );
    map.putIfAbsent('key', () => 'default');
    map.update('name', (v) => v.toUpperCase());

コレクション操作

  • メソッドチェーン、ジェネリクスの使い方です。

    var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    
    // メソッドチェーン
    nums.where((n) => n.isEven).toList();
    // [2, 4, 6, 8, 10]
    nums.map((n) => n * n).toList();
    nums.fold(0, (sum, n) => sum + n); // 55
    nums.reduce((a, b) => a + b);     // 55
    nums.any((n) => n > 5);           // true
    nums.every((n) => n > 0);         // true
    nums.firstWhere((n) => n > 3);    // 4
    nums.take(3).toList();             // [1,2,3]
    nums.skip(7).toList();             // [8,9,10]
    
    // ジェネリクス
    class Box<T> {
      final T value;
      Box(this.value);
    }
    var intBox = Box<int>(42);
    
    // 型制約
    class NumBox<T extends num> {
      final T value;
      NumBox(this.value);
    }
    
    // ジェネリック関数
    T first<T>(List<T> items) => items[0];

非同期プログラミング

Future & async/await

  • 非同期処理の基本とFutureメソッドです。

    // async / await
    Future<String> fetchData() async {
      await Future.delayed(Duration(seconds: 2));
      return 'Data loaded';
    }
    
    void main() async {
      var data = await fetchData();
      print(data);
    }
    
    // Future メソッド
    Future.value('instant');
    Future.error('oops');
    Future.delayed(
      Duration(seconds: 1), () => 'delayed',
    );
    
    // 並行実行
    var results = await Future.wait([
      fetchUser(),
      fetchPosts(),
      fetchComments(),
    ]);
    
    // タイムアウト
    var data = await fetchData()
        .timeout(Duration(seconds: 5));

Stream

  • async*, yield, StreamControllerによるデータストリームです。

    // async* で Stream 生成
    Stream<int> countStream(int max) async* {
      for (var i = 0; i < max; i++) {
        await Future.delayed(Duration(seconds: 1));
        yield i;  // 値を逐次発行
      }
    }
    
    // await for で消費
    await for (var count in countStream(5)) {
      print(count); // 0, 1, 2, 3, 4
    }
    
    // Stream 変換
    stream
        .where((e) => e > 2)
        .map((e) => e * 10)
        .listen((data) => print(data));
    
    // StreamController(手動制御)
    var ctrl = StreamController<String>();
    ctrl.sink.add('data1');
    ctrl.stream.listen((d) => print(d));
    ctrl.close();
    
    // Isolate(並列処理)
    var result = await Isolate.run(() {
      return heavyComputation();
    });

エラーハンドリング

  • try/catch/finally, on句, thenチェーンです。

    // try / catch / finally
    try {
      var result = await riskyOperation();
    } on FormatException catch (e) {
      print('Format error: $e');
    } on HttpException catch (e, stackTrace) {
      print('HTTP error: $e');
      print(stackTrace);
    } catch (e) {
      print('Unknown: $e');
    } finally {
      cleanup();
    }
    
    // then チェーン
    fetchData()
        .then((data) => processData(data))
        .then((result) => saveResult(result))
        .catchError((e) => handleError(e))
        .whenComplete(() => cleanup());

Widget基礎

最小アプリ & StatelessWidget

  • MaterialApp, Scaffold, StatelessWidgetの基本構造です。

    import 'package:flutter/material.dart';
    
    void main() => runApp(const MyApp());
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'My App',
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(
              seedColor: Colors.blue,
            ),
            useMaterial3: true,
          ),
          home: const HomePage(),
        );
      }
    }
    
    // StatelessWidget
    class GreetingCard extends StatelessWidget {
      final String name;
      const GreetingCard({
        super.key, required this.name,
      });
    
      @override
      Widget build(BuildContext context) {
        return Text('Hello, $name!');
      }
    }

StatefulWidget

  • setState, ライフサイクル, initState/disposeです。

    class Counter extends StatefulWidget {
      const Counter({super.key});
    
      @override
      State<Counter> createState() =>
          _CounterState();
    }
    
    class _CounterState extends State<Counter> {
      int _count = 0;
    
      @override
      void initState() {
        super.initState();
        // 初期化処理(1回だけ)
      }
    
      @override
      void dispose() {
        // リソース解放
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Column(children: [
          Text('Count: $_count'),
          ElevatedButton(
            onPressed: () =>
                setState(() => _count++),
            child: const Text('Increment'),
          ),
        ]);
      }
    }

ライフサイクル

メソッドタイミング
createState()StatefulWidget生成時
initState()State生成直後(1回)
didChangeDependencies()依存Widget変更時
build()UIの構築(setState毎)
didUpdateWidget()親からの設定変更時
deactivate()ツリーから除去時
dispose()State完全破棄時

レイアウトWidget

Row & Column

  • 横並び・縦並び, MainAxisAlignment, Expanded/Spacerです。

    // Row(横並び)
    Row(
      mainAxisAlignment:
          MainAxisAlignment.spaceBetween,
      crossAxisAlignment:
          CrossAxisAlignment.center,
      children: [
        const Text('Left'),
        Expanded(child: const Text('Fill')),
        const Text('Right'),
      ],
    )
    
    // Column(縦並び)
    Column(
      mainAxisAlignment:
          MainAxisAlignment.start,
      crossAxisAlignment:
          CrossAxisAlignment.stretch,
      children: [
        const Text('Top'),
        const Spacer(),
        const Text('Bottom'),
      ],
    )
    
    // 便利Widget
    Padding(
      padding: EdgeInsets.all(8), child: w)
    Center(child: widget)
    SizedBox(width: 100, height: 50)
    SizedBox(height: 16) // スペーサー
    Flexible(flex: 2, child: widget)
    Wrap(spacing: 8, children: [...])

Alignment

MainAxisAlignment動作
.start先頭に寄せる
.end末尾に寄せる
.center中央に配置
.spaceBetween均等配置(両端余白なし)
.spaceEvenly均等配置(両端余白あり)
.spaceAround均等配置(両端は半分の余白)

Container & Stack

  • 装飾・余白・重ね合わせレイアウトです。

    // Container
    Container(
      width: 200, height: 100,
      margin: const EdgeInsets.all(16),
      padding: const EdgeInsets.symmetric(
        horizontal: 12, vertical: 8,
      ),
      decoration: BoxDecoration(
        color: Colors.blue,
        borderRadius: BorderRadius.circular(12),
        boxShadow: [BoxShadow(
          color: Colors.black26,
          blurRadius: 10,
        )],
      ),
      child: const Text('Container'),
    )
    
    // Stack(重ね合わせ)
    Stack(children: [
      Image.network('https://...'),
      Positioned(
        bottom: 16, left: 16,
        child: const Text('Overlay'),
      ),
    ])

ListView & GridView

  • スクロール可能なリスト・グリッドレイアウトです。

    // ListView.builder
    ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) => ListTile(
        leading: const Icon(Icons.star),
        title: Text(items[index].title),
        subtitle: Text(items[index].subtitle),
        trailing:
            const Icon(Icons.chevron_right),
        onTap: () {},
      ),
    )
    
    // GridView
    GridView.count(
      crossAxisCount: 2,
      crossAxisSpacing: 8,
      mainAxisSpacing: 8,
      children: List.generate(6,
        (i) => Card(
          child: Center(child: Text('$i')),
        ),
      ),
    )
    
    // Scaffold
    Scaffold(
      appBar: AppBar(title: Text('Title')),
      body: Center(child: Text('Content')),
      floatingActionButton:
          FloatingActionButton(
        onPressed: () {},
        child: const Icon(Icons.add),
      ),
    )

ナビゲーション

Navigator(基本)

  • push, pop, pushReplacement, 値の受け渡しです。

    // 画面遷移(push)
    Navigator.push(context,
      MaterialPageRoute(
        builder: (context) =>
            const DetailPage(),
      ),
    );
    
    // 戻る(pop)
    Navigator.pop(context);
    
    // 値を返して戻る
    Navigator.pop(context, 'result_data');
    
    // 結果を受け取る
    final result = await Navigator.push<String>(
      context,
      MaterialPageRoute(
        builder: (context) =>
            const SelectPage(),
      ),
    );
    
    // 全て置き換え(ログイン後など)
    Navigator.pushReplacement(context,
      MaterialPageRoute(
        builder: (context) => const HomePage(),
      ),
    );
    
    // スタッククリア
    Navigator.pushAndRemoveUntil(
      context,
      MaterialPageRoute(
        builder: (context) => const HomePage(),
      ),
      (route) => false,
    );

GoRouter(宣言的ルーティング)

  • パスパラメータ, ShellRoute, リダイレクトです。

    // GoRouter (go_router パッケージ)
    final router = GoRouter(
      initialLocation: '/',
      routes: [
        GoRoute(
          path: '/',
          builder: (context, state) =>
              const HomePage(),
          routes: [
            GoRoute(
              path: 'detail/:id',
              builder: (context, state) {
                final id =
                    state.pathParameters['id']!;
                return DetailPage(id: id);
              },
            ),
          ],
        ),
        // ShellRoute(共通レイアウト)
        ShellRoute(
          builder: (context, state, child) =>
              AppShell(child: child),
          routes: [
            GoRoute(path: '/home',
              builder: (_, __) => HomePage()),
            GoRoute(path: '/profile',
              builder: (_, __) => ProfilePage()),
          ],
        ),
      ],
      redirect: (context, state) {
        if (!isLoggedIn) return '/login';
        return null;
      },
    );
    
    // 使用
    MaterialApp.router(routerConfig: router)
    
    // ナビゲーション
    context.go('/detail/123');
    context.push('/detail/123');
    context.pop();

状態管理 & パターン

Provider / Riverpod

  • ChangeNotifier, Consumer, ref.watch/readです。

    // Provider パッケージ
    class CounterModel extends ChangeNotifier {
      int _count = 0;
      int get count => _count;
    
      void increment() {
        _count++;
        notifyListeners();
      }
    }
    
    // 提供
    ChangeNotifierProvider(
      create: (_) => CounterModel(),
      child: const MyApp(),
    )
    
    // 消費
    Consumer<CounterModel>(
      builder: (context, counter, child) {
        return Text('${counter.count}');
      },
    )
    // または
    context.watch<CounterModel>(); // rebuild
    context.read<CounterModel>()   // 1回読み
        .increment();
    
    // Riverpod (型安全な状態管理)
    final counterProvider =
        StateNotifierProvider<CounterNotifier, int>(
      (ref) => CounterNotifier(),
    );
    
    class CounterNotifier extends StateNotifier<int> {
      CounterNotifier() : super(0);
      void increment() => state++;
    }
    
    // ConsumerWidget で使用
    class Page extends ConsumerWidget {
      @override
      Widget build(BuildContext context,
          WidgetRef ref) {
        final count = ref.watch(counterProvider);
        return Text('$count');
      }
    }
    
    // ref メソッド
    ref.watch(p);   // リアクティブ監視
    ref.read(p);    // 1回読み取り
    ref.listen(p, (prev, next) { /* 副作用 */ });

よく使うパターン

  • FutureBuilder, MediaQuery, ダイアログ表示です。

    // FutureBuilder
    FutureBuilder<String>(
      future: fetchData(),
      builder: (context, snapshot) {
        if (snapshot.connectionState ==
            ConnectionState.waiting) {
          return CircularProgressIndicator();
        }
        if (snapshot.hasError) {
          return Text('Error: ${snapshot.error}');
        }
        return Text(snapshot.data!);
      },
    )
    
    // StreamBuilder
    StreamBuilder<int>(
      stream: countStream,
      builder: (context, snapshot) {
        return Text('${snapshot.data ?? 0}');
      },
    )
    
    // MediaQuery(レスポンシブ)
    final size = MediaQuery.of(context).size;
    final isTablet = size.width > 600;
    
    // Theme アクセス
    final theme = Theme.of(context);
    final colors = theme.colorScheme;
    
    // ダイアログ
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Confirm'),
        content: const Text('Are you sure?'),
        actions: [
          TextButton(
            onPressed: () =>
                Navigator.pop(context),
            child: const Text('Cancel'),
          ),
          FilledButton(
            onPressed: () { /* 処理 */ },
            child: const Text('OK'),
          ),
        ],
      ),
    );

引用・参考リンク

Related Goods

  • iPhone/Android両対応アプリの開発テクニックを実践的に解説。
Flutterでのクロスプラットフォーム開発を本格的に学べます。
    iPhone/Android両対応アプリの開発テクニックを実践的に解説。 Flutterでのクロスプラットフォーム開発を本格的に学べます。
    詳細をみる
  • ケーブルに取り付け可能なTypeCとLightningの変換アダプタです。
スタイリッシュなデザインで、Apple製品との相性抜群です。
    ケーブルに取り付け可能なTypeCとLightningの変換アダプタです。 スタイリッシュなデザインで、Apple製品との相性抜群です。
    詳細をみる
  • お気に入りのサウンドデバイスをすぐ取り出せる位置にディスプレイさせておくことができます。
    お気に入りのサウンドデバイスをすぐ取り出せる位置にディスプレイさせておくことができます。
    詳細をみる

WebTerm - Recommended tools

WebTermは、ブラウザでLinuxコマンド・Gitコマンドを安全に実行でき、チュートリアル式で学べるターミナルサンドボックスです。
AIコーディングツールの普及に伴い、CLIの基礎知識を身につける重要性は増しています。実際のターミナルを操作するのに抵抗がある方でも、WebTermはローカル環境を壊す心配がありません。「会員登録不要・無料」で利用でき、学習環境として最適です。

WebTerm Logo

WebTerm

Browser Terminal Sandbox for Learning CLI

開く

All Cheatsheets

エンジニア・プログラマー向けの便利なチートシートを多数まとめています(SP/Tablet/PC対応)
すべてのチートシートを見る