Chuyển đến nội dung chính

レッスン 18: コード生成とフリーズ

build_runner ワークフロー。不変のデータ クラス、共用体型の場合はフリーズされます。カスタム コンバーターを使用した json_serializable。 auto_route、注入可能。コード生成のベスト プラクティス。

💻 プログラミング — レッスン 18 レッスン 18: コード生成とフリーズ

フラッター&ダーツ: 基本から上級まで

パート 5: アーキテクチャとパターン

xdev.asia

1. 凍結 — 不変のデータクラス

dependencies:
  freezed_annotation: ^2.4.0
  json_annotation: ^4.8.0

dev_dependencies:
  freezed: ^2.5.0
  json_serializable: ^6.7.0
  build_runner: ^2.4.0
import 'package:freezed_annotation/freezed_annotation.dart';
part 'product.freezed.dart';
part 'product.g.dart';

@freezed
class Product with _$Product {
  const factory Product({
    required String id,
    required String name,
    required double price,
    @Default('') String description,
    @JsonKey(name: 'image_url') String? imageUrl,
    @Default([]) List<String> tags,
  }) = _Product;

  factory Product.fromJson(Map<String, dynamic> json) => _$ProductFromJson(json);
}

// Sử dụng — immutable copyWith
final product = Product(id: '1', name: 'Laptop', price: 999);
final updated = product.copyWith(price: 899); // Immutable update

2. フリーズされたユニオン型 — シールされたクラス

@freezed
sealed class ApiResult<T> with _$ApiResult<T> {
  const factory ApiResult.success(T data) = ApiSuccess;
  const factory ApiResult.error(String message, {int? statusCode}) = ApiError;
  const factory ApiResult.loading() = ApiLoading;
}

// Pattern matching
final result = await repository.getProducts();
result.when(
  success: (data) => state = ProductLoaded(data),
  error: (message, statusCode) => state = ProductError(message),
  loading: () => state = const ProductLoading(),
);

// maybeWhen — xử lý một số case
result.maybeWhen(
  success: (data) => showProducts(data),
  orElse: () => showPlaceholder(),
);

3. インジェクタブル — DI コード生成

// Đánh dấu với annotations
@injectable
class ProductRepository {
  final ApiClient _api;
  final ProductCache _cache;

  ProductRepository(this._api, this._cache);
}

@lazySingleton
class ApiClient {
  final Dio _dio;
  ApiClient(this._dio);
}

@module
abstract class RegisterModule {
  @lazySingleton
  Dio get dio => Dio(BaseOptions(baseUrl: 'https://api.example.com'));
}

// Generated — injection.config.dart
@InjectableInit()
void configureDependencies() => getIt.init();

4. ビルドランナーのワークフロー

# One-time build
dart run build_runner build --delete-conflicting-outputs

# Watch mode — auto-rebuild
dart run build_runner watch --delete-conflicting-outputs

# Clean generated files
dart run build_runner clean
パッケージ目的生成されたファイル
冷凍不変クラス、共用体*.フリーズ.ダーツ
json_serializableJSONシリアル化*.g.ダーツ
注射可能なDI登録インジェクション.config.dart
自動ルートルーターの生成*.gr.ダーツ
リバーポッドジェネレーターリバーポッドプロバイダー*.g.ダーツ

次の記事: Flutter でのテスト。