When building a mobile application, it is common to have different configurations for different environments. For example, you might have different API endpoints for your development, staging, and production environments. In Flutter, you can use flavors to build and manage these different configurations.
Flavors are a way to create different builds of the same application with different configurations. With flavors, you can easily create different versions of your app for different environments without having to manually change the code every time. In this article, we will learn about flavors in Flutter and how to use them to build and manage different versions of your app.
What are Flavors in Flutter?
Flavors in Flutter are a way to create different builds of the same application with different configurations. Each flavor has its own set of resources, configurations, and dependencies. You can use flavors to create different versions of your app for different environments, such as development, staging, and production.
Flavors are similar to product flavors in Android and schemes in iOS. They allow you to build and manage different versions of your app from a single codebase. This can save you time and effort when building and deploying your app.
How to Create Flavors in Flutter
To create flavors in Flutter, you need to create different build configurations for each flavor. You can do this by creating different files for each flavor in the lib directory. For example, you can create the following files for two different flavors:
In flavor_config.dart
enum Environment { STAGE, PRODUCTION }
class FlavourConfig {
static late Map<String, dynamic> config;
static getEnv(Environment env) {
if (env == Environment.PRODUCTION) {
config = Config.productionData;
} else if (env == Environment.STAGE) {
config = Config.stageData;
}
}
static String get baseURL {
return config[Config.BASE_URL] as String;
}
static String get appTitle {
return config[Config.APP_TITLE] as String;
}
}
class Config {
static const BASE_URL = 'BASE_URL';
static const APP_TITLE = 'APP_TITLE';
static Map<String, dynamic> stageData = {
BASE_URL: 'https://stage.com',
APP_TITLE: 'This is stage',
};
static Map<String, dynamic> productionData = {
BASE_URL: 'https://production.com',
APP_TITLE: 'This is production',
};
}
In main_common.dart
import 'package:flutter/material.dart';
import 'flavor_config.dart';
class MainCommon extends StatefulWidget {
const MainCommon({Key? key}) : super(key: key);
@override
State<MainCommon> createState() => _MainCommonState();
}
class _MainCommonState extends State<MainCommon> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(FlavourConfig.appTitle)),
body: Padding(
padding: const EdgeInsets.all(30),
child: Center(
child: Column(
children: [
const Padding(
padding: EdgeInsets.all(8.0),
child: Text("BASE URL IS"),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(FlavourConfig.baseURL),
)
],
),
),
),
);
}
}
In main_production.dart
import 'package:flutter/material.dart';
import 'flavor_config.dart';
import 'main_common.dart';
void main() {
FlavourConfig.getEnv(Environment.PRODUCTION);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MainCommon(),
);
}
}
In main_stage.dart
import 'package:flutter/material.dart';
import 'flavor_config.dart';
import 'main_common.dart';
void main() {
FlavourConfig.getEnv(Environment.STAGE);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MainCommon(),
);
}
}