Flutter ベストプラクティス

このセクションでは、Flutter 開発におけるベストプラクティスとコーディング規約を紹介します。


コード規約

命名規則

種類規則例
クラス名アッパーキャメルケースMyHomePage
関数/変数ローワーキャメルケースuserName, getData
定数アッパーキャメルケース + k プレフィックスkMaxCount
ファイル小文字 + アンダースコアmy_home_page.dart

例:正しい命名

// クラス名 - アッパーキャメルケース
class UserProfilePage extends StatelessWidget {}

// 関数 - ローワーキャメルケース
void fetchUserData() {}

// 変数 - ローワーキャメルケース
String userName = '张三';

// 定数 - k プレフィックス
const int kMaxRetryCount = 3;
const String kAppName = '私のアプリ';

// 列挙型 - アッパーキャメルケース
enum AppState { loading, success, error }

// ファイル名 - 小文字アンダースコア
// user_profile_page.dart

パフォーマンス最適化

1. 不要な rebuild を避ける

例:const コンストラクタを使用する

// 推奨:const を使用して rebuild を減らす
const Text('Hello')              // rebuild されない
const SizedBox(width: 10)

// 非推奨:毎回の build で新しいオブジェクトが作成される
Text('Hello')                   // rebuild される

// リストで const を使用する
ListView(
  children: const [
    Text('A'),
    Text('B'),
    Text('C'),
  ],
)

2. keys を使用してリストのパフォーマンスを最適化する

例:keys の正しい使い方

// リスト項目に一意の key を追加する
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ListTile(
      key: ValueKey(items[index].id),  // 一意の識別子を key として使用する
      title: Text(items[index].name),
    );
  },
)

3. リスト項目の遅延読み込み

例:ListView.builder を使用する

// 推奨:builder を使用した遅延読み込み
ListView.builder(
  itemCount: 1000,  // 大きなリストでは必須
  itemBuilder: (context, index) {
    return ListTile(title: Text('Item $index'));
  },
)

// 非推奨:children で大きなリストを構築する
ListView(
  children: List.generate(1000, (i) => Text('Item $i')),
)

プロジェクト構造

例:推奨されるプロジェクト構造

// lib/
// ├── main.dart # エントリーファイル
// ├── app.dart # アプリ設定
// ├── core/ # コア機能
// │ ├── constants/ # 定数
// │ ├── theme/ # テーマ
// │ ├── utils/ # ユーティリティクラス
// │ └── extensions/ # 拡張
// ├── data/ # データ層
// │ ├── models/ # データモデル
// │ ├── repositories/ # リポジトリ
// │ └── services/ # ネットワークサービス
// ├── domain/ # ドメイン層
// │ └── entities/ # エンティティ
// ├── presentation/ # プレゼンテーション層
// │ ├── pages/ # ページ
// │ ├── widgets/ # ウィジェット
// │ └── providers/ # 状態管理
// └── routes/ # ルート

エラーハンドリング

例:グローバルエラーハンドリング

void main() {
  // グローバル例外のキャッチ
  FlutterError.onError = (details) {
    // エラーを記録
    print('Flutter Error: ${details.exception}');
    // エラーをサーバーに送信
    reportError(details.exception);
  };

  // Zone 例外のキャッチ
  runZonedGuarded(() {
    runApp(const MyApp());
  }, (error, stackTrace) {
    print('Zone Error: $error');
    reportError(error);
  });
}

ベストプラクティスに従うことで、コードの保守性が高まり、パフォーマンスが向上し、本番環境でのバグを減らすことができます。

その他の拡張