Lewati ke konten utama

Flutter — Dart

Standar pengembangan aplikasi cross-platform menggunakan Flutter dan Dart.

Tech Stack​

KategoriPackageVersi Min.
LanguageDart3.13+
FrameworkFlutter3.47+
State ManagementBloc / RiverpodLatest
NavigationGoRouterLatest
DIGetIt + InjectableLatest
NetworkingDio5.x
Serializationjson_serializable + freezedLatest
Image Loadingcached_network_imageLatest
Local DBDrift (disarankan) / ObjectBoxLatest
Testingflutter_test, mockito, bloc_test—
Lintingflutter_lints / very_good_analysisLatest
CI/CDFastlane + GitLab CI—
Hive dan Isar sudah stalled

Hive dan Isar sudah tidak aktif dikembangkan oleh maintainer aslinya — jangan pakai keduanya untuk project baru. Gunakan Drift (SQL, type-safe, aktif dimaintain, jalan di semua platform termasuk web) sebagai default, atau ObjectBox kalau butuh NoSQL object store dengan built-in sync engine. Project lama yang masih pakai Hive/Isar boleh lanjut jalan, tapi rencanakan migrasi.

Project Structure​

lib/
├── main.dart # Entry point
├── app/
│ ├── app.dart # MaterialApp / router setup
│ └── di/ # Dependency injection setup
├── core/
│ ├── constants/
│ ├── extensions/
│ ├── theme/ # AppTheme, colors, typography
│ ├── utils/
│ └── network/ # Dio client, interceptors
├── data/
│ ├── datasources/
│ │ ├── remote/ # API data sources
│ │ └── local/ # Local data sources
│ ├── models/ # DTOs (with json_serializable)
│ └── repositories/ # Repository implementations
├── domain/
│ ├── entities/ # Domain entities (with freezed)
│ ├── repositories/ # Repository interfaces
│ └── usecases/ # Use cases
├── presentation/
│ ├── screens/ # Per-screen folders
│ │ ├── home/
│ │ │ ├── home_screen.dart
│ │ │ ├── home_cubit.dart # or home_bloc.dart
│ │ │ └── widgets/ # Screen-specific widgets
│ │ └── profile/
│ └── widgets/ # Shared reusable widgets
└── l10n/ # Localization
test/
├── unit/
├── widget/
└── integration/

Coding Standards​

Dart Style Guide​

  • Ikuti Effective Dart.
  • Gunakan very_good_analysis atau custom analysis_options.yaml.
  • Maksimum line length: 80 karakter (Dart default).

Bloc Pattern​

// ✅ Good - Cubit/Bloc dengan state class terpisah
class UserCubit extends Cubit<UserState> {
final GetUserUseCase _getUserUseCase;

UserCubit(this._getUserUseCase) : super(const UserState.initial());

Future<void> loadUser(String id) async {
emit(const UserState.loading());
try {
final user = await _getUserUseCase(id);
emit(UserState.success(user));
} catch (e) {
emit(UserState.error(e.toString()));
}
}
}


sealed class UserState with _$UserState {
const factory UserState.initial() = _Initial;
const factory UserState.loading() = _Loading;
const factory UserState.success(User user) = _Success;
const factory UserState.error(String message) = _Error;
}

Widget Best Practices​

// ✅ Good - Stateless, parameter driven
class UserCard extends StatelessWidget {
const UserCard({
super.key,
required this.user,
required this.onTap,
});

final UserEntity user;
final VoidCallback onTap;


Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Card(
child: ListTile(
title: Text(user.name),
subtitle: Text(user.email),
),
),
);
}
}

Build & Run​

# Run development
flutter run

# Run tests
flutter test

# Analyze code
flutter analyze

# Build APK
flutter build apk --release

# Build iOS
flutter build ios --release

# Code generation (freezed, json_serializable)
dart run build_runner build --delete-conflicting-outputs
Code Generation

Setiap perubahan pada model freezed atau json_serializable wajib diikuti dengan build_runner build sebelum commit.