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
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'),
],
)
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),
);
},
)
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')),
)
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/ # ルート
// ├── 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);
});
}
// グローバル例外のキャッチ
FlutterError.onError = (details) {
// エラーを記録
print('Flutter Error: ${details.exception}');
// エラーをサーバーに送信
reportError(details.exception);
};
// Zone 例外のキャッチ
runZonedGuarded(() {
runApp(const MyApp());
}, (error, stackTrace) {
print('Zone Error: $error');
reportError(error);
});
}
その他の拡張ベストプラクティスに従うことで、コードの保守性が高まり、パフォーマンスが向上し、本番環境でのバグを減らすことができます。