Answer
Overview
Flutter mobile app standards refer to best practices for code quality, performance, security, accessibility, and user experience. Following these standards ensures maintainable, scalable, and production-ready apps.
1. Code Quality Standards
Project Structure
Feature-first structure (recommended for large apps):
textlib/ features/ authentication/ data/ domain/ presentation/ home/ data/ domain/ presentation/ core/ utils/ constants/ widgets/ main.dart
Layer-first structure (simple apps):
textlib/ data/ domain/ presentation/ main.dart
Naming Conventions
dart// ✅ Classes: PascalCase class UserRepository {} // ✅ Files: snake_case // user_repository.dart // ✅ Variables/functions: camelCase String userName = 'Alice'; void fetchUserData() {} // ✅ Constants: lowerCamelCase or UPPER_SNAKE_CASE const maxRetries = 3; const MAX_RETRIES = 3; // ✅ Private members: _prefix class User { String _password; }
Dart Analysis (Linting)
analysis_options.yaml:
yamlinclude: package:flutter_lints/flutter.yaml linter: rules: - prefer_const_constructors - prefer_const_literals_to_create_immutables - avoid_print - avoid_unnecessary_containers - sized_box_for_whitespace - use_key_in_widget_constructors - prefer_single_quotes - always_declare_return_types
2. Performance Standards
Widget Optimization
dart// ✅ Use const constructors const Text('Hello'); const SizedBox(height: 16); // ✅ Avoid rebuilding entire tree class MyWidget extends StatelessWidget { Widget build(BuildContext context) { return Column( children: [ const HeaderWidget(), // Const — never rebuilds DynamicWidget(), // Only this rebuilds ], ); } } // ✅ Extract widgets for reuse class _BuildItem extends StatelessWidget { final String text; const _BuildItem(this.text); Widget build(BuildContext context) { return Text(text); } }
Image Optimization
dart// ✅ Use cached_network_image CachedNetworkImage( imageUrl: 'https://example.com/image.jpg placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context, url, error) => Icon(Icons.error), ) // ✅ Specify image dimensions Image.network( 'https://example.com/image.jpg width: 300, height: 200, fit: BoxFit.cover, ) // ❌ Avoid loading large images without caching Image.network('https://example.com/10mb.jpg') // ❌
List Performance
dart// ✅ Use ListView.builder for long lists ListView.builder( itemCount: 1000, itemBuilder: (context, index) => ListTile(title: Text('Item $index')), ) // ❌ Avoid ListView with all items ListView( children: List.generate(1000, (i) => ListTile(...)), // ❌ Builds all at once )
3. State Management Standards
Choose based on app complexity:
| App Size | Recommended | Alternative |
|---|---|---|
| Small | Provider, Riverpod | setState |
| Medium | BLoC, Riverpod | GetX |
| Large | BLoC, Riverpod | Clean Architecture + BLoC |
Example (BLoC):
dart// ✅ Separate business logic from UI class UserBloc extends Bloc<UserEvent, UserState> { UserBloc() : super(UserInitial()) { on<FetchUser>(_onFetchUser); } Future<void> _onFetchUser(FetchUser event, Emitter<UserState> emit) async { emit(UserLoading()); try { final user = await userRepository.fetchUser(event.id); emit(UserLoaded(user)); } catch (e) { emit(UserError(e.toString())); } } }
4. Security Standards
API Keys
dart// ❌ Never hardcode API keys const apiKey = 'sk-1234567890'; // ❌ // ✅ Use environment variables flutter run --dart-define=API_KEY=sk-1234567890 // Access in code const apiKey = String.fromEnvironment('API_KEY');
Secure Storage
dart// ✅ Use flutter_secure_storage for sensitive data import 'package:flutter_secure_storage/flutter_secure_storage.dart'; final storage = FlutterSecureStorage(); await storage.write(key: 'auth_token', value: token); final token = await storage.read(key: 'auth_token');
Network Security
dart// ✅ Use HTTPS only final response = await http.get(Uri.parse('https://api.example.com')); // ❌ Avoid HTTP (insecure) // http://api.example.com ❌
5. Accessibility Standards
dart// ✅ Add semantic labels Semantics( label: 'Close button', child: IconButton( icon: Icon(Icons.close), onPressed: () {}, ), ) // ✅ Use accessible colors (contrast ratio 4.5:1) Text( 'Readable Text', style: TextStyle( color: Colors.black, // ✅ High contrast backgroundColor: Colors.white, ), ) // ✅ Support screen readers ExcludeSemantics( child: DecorativeImage(), // Decorative — skip for screen readers )
6. Testing Standards
dart// ✅ Unit tests for business logic test('UserRepository fetches user', () async { final user = await userRepository.fetchUser('123'); expect(user.name, 'Alice'); }); // ✅ Widget tests for UI testWidgets('Login button triggers login', (tester) async { await tester.pumpWidget(LoginPage()); await tester.tap(find.byType(ElevatedButton)); await tester.pump(); expect(find.text('Loading...'), findsOneWidget); }); // ✅ Integration tests for flows testWidgets('Complete login flow', (tester) async { await tester.pumpWidget(MyApp()); await tester.enterText(find.byKey(Key('email')), 'test@example.com'); await tester.enterText(find.byKey(Key('password')), 'password'); await tester.tap(find.text('Login')); await tester.pumpAndSettle(); expect(find.text('Welcome'), findsOneWidget); });
Coverage target: 80%+ for critical code.
7. Error Handling Standards
dart// ✅ Handle errors gracefully try { final data = await fetchData(); } catch (e) { logger.error('Failed to fetch data', e); showSnackBar('Something went wrong. Please try again.'); } // ✅ Use Result/Either pattern (functional error handling) class Result<T> { final T? data; final String? error; Result.success(this.data) : error = null; Result.failure(this.error) : data = null; } Future<Result<User>> fetchUser(String id) async { try { final user = await api.getUser(id); return Result.success(user); } catch (e) { return Result.failure(e.toString()); } }
8. Documentation Standards
dart/// Fetches user data from the API. /// /// Returns a [User] object if successful. /// Throws [NetworkException] if network fails. /// /// Example: /// ```dart /// final user = await fetchUser('123'); /// print(user.name); /// ``` Future<User> fetchUser(String id) async { final response = await http.get(Uri.parse('https://api.example.com/users/$id')); if (response.statusCode == 200) { return User.fromJson(jsonDecode(response.body)); } else { throw NetworkException('Failed to fetch user'); } }
9. Dependency Management
yaml# ✅ Pin major versions dependencies: http: ^1.1.0 # 1.x.x (SemVer) provider: ^6.0.0 # ✅ Separate dev dependencies dev_dependencies: flutter_test: sdk: flutter build_runner: ^2.4.0 mockito: ^5.4.0 # ✅ Keep dependencies updated # Run: flutter pub outdated
10. Build Standards
Flavors (Dev, Staging, Prod)
dart// main_dev.dart void main() { runApp(MyApp(environment: Environment.dev)); } // main_prod.dart void main() { runApp(MyApp(environment: Environment.prod)); }
Build commands:
bash# Dev build flutter build apk --flavor dev -t lib/main_dev.dart # Production build flutter build apk --flavor prod -t lib/main_prod.dart --release
11. UI/UX Standards
dart// ✅ Follow Material Design or Cupertino guidelines MaterialApp( theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), ) // ✅ Responsive design LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth > 600) { return TabletLayout(); } else { return MobileLayout(); } }, ) // ✅ Handle loading states if (isLoading) CircularProgressIndicator() else if (hasError) ErrorWidget(error: error) else ContentWidget(data: data)
12. Checklist for Production
- No statements (use logger)text
print() - No hardcoded API keys
- Error handling in all async calls
- Loading states for all API calls
- Accessibility labels on interactive widgets
- Images optimized and cached
- Tests written (80%+ coverage)
- Lint errors fixed ()text
flutter analyze - Obfuscated code ()text
--obfuscate --split-debug-info - ProGuard enabled (Android)
- Bitcode enabled (iOS)
Summary
| Category | Standard |
|---|---|
| Code | Follow linter rules, naming conventions |
| Performance | Use const, ListView.builder, image caching |
| State | BLoC/Riverpod for complex apps |
| Security | Secure storage, no hardcoded keys |
| Accessibility | Semantic labels, contrast ratios |
| Testing | 80%+ coverage |
| Error Handling | Try-catch, user-friendly messages |
| Documentation | Dartdoc comments for public APIs |
Learn more: