Answer
What are Flavors in Flutter?
Flavors (also called build variants or product flavors) are different versions of your Flutter application that share the same codebase but have different configurations, features, or branding. They allow you to build multiple variants of your app from a single codebase, such as development, staging, and production versions.
Common Use Cases for Flavors
| Flavor Type | Use Case | Example |
|---|---|---|
| Environment-based | Different API endpoints | dev, staging, production |
| Feature-based | Different feature sets | free, premium, enterprise |
| Brand-based | White-label apps | Client A, Client B, Client C |
| Platform-based | Region-specific versions | US, EU, Asia versions |
Setting Up Flavors
1. Android Configuration (android/app/build.gradle)
gradleandroid { defaultConfig { applicationId "com.example.myapp" // ... other config } flavorDimensions "environment" productFlavors { dev { dimension "environment" applicationIdSuffix ".dev" versionNameSuffix "-dev" resValue "string", "app_name", "MyApp Dev" } staging { dimension "environment" applicationIdSuffix ".staging" versionNameSuffix "-staging" resValue "string", "app_name", "MyApp Staging" } production { dimension "environment" resValue "string", "app_name", "MyApp" } } }
2. iOS Configuration (ios/Runner.xcodeproj)
In Xcode:
- Select the project in the navigator
- Go to "Info" tab
- Duplicate the "Debug" and "Release" configurations
- Name them (e.g., Debug-dev, Release-production)
Or modify
text
ios/Flutter/Debug.xcconfigtext
ios/Flutter/Release.xcconfigxcconfig// Debug-dev.xcconfig #include "Generated.xcconfig" APP_NAME=MyApp Dev APP_BUNDLE_ID=com.example.myapp.dev
3. Flutter Flavor Configuration
dart// lib/main_dev.dart import 'package:flutter/material.dart'; import 'app.dart'; import 'config/app_config.dart'; void main() { AppConfig.setFlavor(Flavor.dev); runApp(MyApp()); } // lib/main_staging.dart import 'package:flutter/material.dart'; import 'app.dart'; import 'config/app_config.dart'; void main() { AppConfig.setFlavor(Flavor.staging); runApp(MyApp()); } // lib/main_production.dart import 'package:flutter/material.dart'; import 'app.dart'; import 'config/app_config.dart'; void main() { AppConfig.setFlavor(Flavor.production); runApp(MyApp()); }
Flavor Configuration Class
dart// lib/config/app_config.dart enum Flavor { dev, staging, production, } class AppConfig { static Flavor? _flavor; static void setFlavor(Flavor flavor) { _flavor = flavor; } static Flavor get flavor => _flavor ?? Flavor.production; static String get appName { switch (flavor) { case Flavor.dev: return 'MyApp Dev'; case Flavor.staging: return 'MyApp Staging'; case Flavor.production: return 'MyApp'; } } static String get apiBaseUrl { switch (flavor) { case Flavor.dev: return 'https://dev-api.example.com case Flavor.staging: return 'https://staging-api.example.com case Flavor.production: return 'https://api.example.com } } static bool get isProduction => flavor == Flavor.production; static bool get isDevelopment => flavor == Flavor.dev; }
Running Different Flavors
bash# Run dev flavor flutter run --flavor dev -t lib/main_dev.dart # Run staging flavor flutter run --flavor staging -t lib/main_staging.dart # Run production flavor flutter run --flavor production -t lib/main_production.dart # Build APK for specific flavor flutter build apk --flavor production -t lib/main_production.dart # Build iOS for specific flavor flutter build ios --flavor production -t lib/main_production.dart
VS Code Launch Configuration
Create
text
.vscode/launch.jsonjson{ "version": "0.2.0", "configurations": [ { "name": "Dev", "request": "launch", "type": "dart", "program": "lib/main_dev.dart", "args": ["--flavor", "dev"] }, { "name": "Staging", "request": "launch", "type": "dart", "program": "lib/main_staging.dart", "args": ["--flavor", "staging"] }, { "name": "Production", "request": "launch", "type": "dart", "program": "lib/main_production.dart", "args": ["--flavor", "production"] } ] }
Best Practices
- Use Environment Variables: Store sensitive data in environment variables, not in code
- Different App Icons: Use different icons for each flavor to easily identify them
- Separate Firebase Projects: Use different Firebase configurations for each flavor
- Database Separation: Use different database names/endpoints for each environment
- Analytics Tracking: Separate analytics properties for each flavor
Popular Packages for Flavor Management
- flutter_flavor: Simplifies flavor configuration
- flutter_config: Manages environment variables
- flutter_dotenv: Loads configuration from filestext
.env
yaml# pubspec.yaml dependencies: flutter_flavor: ^3.1.0 flutter_dotenv: ^5.1.0
Important: Never commit sensitive API keys or credentials to your repository. Use environment variables or secure secret management for production builds.
Documentation: Flutter Build and Release