DEV Community

Cover image for How to Use Environments in Flutter: Setting Up with Flavors
مصعب يوسف
مصعب يوسف

Posted on Originally published at systemweakness.com on

How to Use Environments in Flutter: Setting Up with Flavors

How to Use Environments in Flutter: Setting Up with Flavors

In software development, environments are distinct configurations used to develop, test, and deploy applications. These environments are crucial for ensuring that software behaves as expected across different stages of development, from local development to production. In this article, we’ll explore what environments are, why we use them, and how to leverage them effectively in Flutter using the Flavor package. We’ll also provide a detailed step-by-step guide to set up flavors in your Flutter project.

What Are Environments?

Environments in software development represent different configurations or contexts in which an application runs. The most common environments are:

  1. Development: This is where developers write code and implement new features. The development environment often includes tools like debugging utilities, mock data, and enhanced logging for easier troubleshooting.
  2. Testing/Staging: This environment mimics the production environment as closely as possible, allowing QA teams to verify features and find bugs before release. It is used to ensure that the software behaves correctly in a controlled but realistic setting, using data that closely resembles real-world scenarios without impacting live users.
  3. Production: This is the environment where the end-users interact with the application. The production environment is optimized for performance, security, and scalability, with features that are fully functional and thoroughly tested.

Using separate environments allows for safe testing of new features, rapid development, and minimized risk to end-users. Developers can isolate issues, testers can validate functionality, and operations teams can optimize performance and scalability without affecting live users.

Why Do We Use Environments?

Environments are essential for ensuring application stability, smooth deployment, and efficient development. Here are some key reasons why environments are used in programming:

  1. Code Isolation: Different environments allow developers to isolate new features or fixes, ensuring that changes do not directly impact the live version of the application.
  2. Safe Testing: Environments such as staging or QA allow for testing and verification before code is deployed to the production environment. This reduces the risk of introducing bugs or performance issues to end-users.
  3. Version Management: Different environments allow for maintaining different versions of the application, making it easier to manage features across the development lifecycle. Developers can work on new features without disrupting the stable version used by end-users.
  4. Configuration Management: Environments allow developers to set different configuration values, such as API endpoints, feature toggles, and logging levels, based on the context in which the application is running. This helps ensure that each environment is tailored for its intended purpose, such as debugging during development or optimizing for performance in production.
  5. User Experience Consistency: Using different environments helps to maintain a consistent user experience across various stages of development. For example, performance optimizations in staging ensure that users experience a smooth and functional application in production.

How to Use Environments in Flutter with Flavors

In Flutter, environments are typically managed using Flavors. Flavors allow you to create multiple versions of your app, each tailored for a specific environment (e.g., dev, staging, production). Flutter flavors help developers streamline the process of managing separate configurations, assets, and builds for each environment.

Below, we’ll guide you through setting up flavors for your Flutter project using the Flavor package, from start to finish.

Step-by-Step Guide to Using Flavors in Flutter

Step 1: Add Dependencies

To begin, add the necessary dependencies to your pubspec.yaml file.

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.0 # Optional - used for state management
  flavor: ^2.0.0 # Package for managing flavors
Enter fullscreen mode Exit fullscreen mode

After adding the dependencies, run the following command to install them:

flutter pub get
Enter fullscreen mode Exit fullscreen mode

Step 2: Create Environment Configuration Files

To manage different environments, create separate configuration files in the lib directory, such as config_dev.dart, config_staging.dart, and config_prod.dart. Each of these files will contain environment-specific settings.

Example for config_dev.dart:

class AppConfig {
  static const String apiUrl = "https://dev.api.example.com";
  static const String environment = "development";
  static const String featureToggle = "newFeatureDev";
}
Enter fullscreen mode Exit fullscreen mode

Example for config_prod.dart:

class AppConfig {
  static const String apiUrl = "https://api.example.com";
  static const String environment = "production";
  static const String featureToggle = "newFeatureProd";
}
Enter fullscreen mode Exit fullscreen mode

These files provide environment-specific values, such as different API URLs, feature toggles, and configuration settings, which will be used based on the selected flavor.

Step 3: Set Up Flavor Configuration

Next, you need to configure flavors in the android and ios folders of your Flutter project.

Android Configuration

  1. Open the android/app/build.gradle file and add the flavor definitions within the android block:
android {
    ...
    flavorDimensions "environment"
    productFlavors {
        dev {
            dimension "environment"
            applicationIdSuffix ".dev"
            versionNameSuffix "-dev"
        }
        staging {
            dimension "environment"
            applicationIdSuffix ".staging"
            versionNameSuffix "-staging"
        }
        production {
            dimension "environment"
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

In the above code, we defined three flavors: dev, staging, and production. Each flavor can have its own settings, such as an application ID suffix or version name suffix, allowing for easy identification and differentiation of builds.

  1. Add Environment-Specific Icons (Optional): You can add different app icons for each flavor to help distinguish between them. Place your icons in different folders within android/app/src (e.g., src/dev/res or src/staging/res). This helps visually identify which version of the app is running.

iOS Configuration

  1. Open Xcode and navigate to the project settings for your iOS app.
  2. Duplicate the existing scheme: For each environment, create a new scheme (e.g., Dev, Staging, Production). This will allow you to build and run different flavors of your app.
  3. Configure Build Settings: In the Build Settings, add custom preprocessor macros for each environment (e.g., DEV, STAGING, PRODUCTION). This will enable you to apply specific settings based on the environment, such as API keys or server URLs.

Step 4: Modify the Main Entry Point

Modify your app’s entry point (main.dart) to load the appropriate environment configuration based on the selected flavor. Create different entry points for each flavor in the lib folder (e.g., main_dev.dart, main_staging.dart, main_prod.dart).

Example for main_dev.dart:

import 'package:flutter/material.dart';
import 'config_dev.dart';
import 'my_app.dart';

void main() {
  runApp(MyApp(config: AppConfig()));
}
Enter fullscreen mode Exit fullscreen mode

Example for my_app.dart:

import 'package:flutter/material.dart';

class MyApp extends StatelessWidget {
  final AppConfig config;
  MyApp({required this.config});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Flavors',
      home: Scaffold(
        appBar: AppBar(title: Text('Environment: ${config.environment}')),
        body: Center(
          child: Text('API URL: ${config.apiUrl}'),
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

This setup ensures that the correct environment configuration is loaded based on the flavor you run.

Step 5: Run Your App with Different Flavors

Now that you’ve set up flavors, you can run your app with different configurations using the Flutter CLI.

To run the development flavor:

flutter run --flavor dev -t lib/main_dev.dart
Enter fullscreen mode Exit fullscreen mode

To run the staging flavor:

flutter run --flavor staging -t lib/main_staging.dart
Enter fullscreen mode Exit fullscreen mode

To run the production flavor:

flutter run --flavor production -t lib/main_prod.dart
Enter fullscreen mode Exit fullscreen mode

These commands allow you to specify the flavor and the appropriate entry point for each environment. You can also create scripts or aliases for quick flavor builds, which makes running specific environments even more efficient.

Benefits of Using Flavors in Flutter

  1. Better Configuration Management: With flavors, you can manage different configurations easily, such as API endpoints, feature flags, logging settings, and third-party service keys. Each flavor can be configured to use different variables, allowing you to customize the behavior of the application for each environment.
  2. Seamless Testing: Flavors allow testers to test the app in different environments (e.g., staging vs. production) without requiring multiple apps. This ensures that any potential issues are caught before releasing to production, improving the quality of the final product.
  3. Environment-Specific Builds: Developers can build environment-specific versions of the app, each with its own app icon, branding, and behavior. This makes it easier to distinguish between different builds, especially during the testing and QA phases.
  4. Faster Development and Debugging: Flavors provide a way to switch between different environments quickly, enabling developers to debug issues and implement features specific to an environment without manually changing configuration values each time.
  5. Reduced Risk: By keeping development, testing, and production environments separate, the risk of deploying unfinished features or bugs to production is minimized. This also ensures that sensitive data and configurations, such as production API keys, are not accidentally exposed during development.

Conclusion

Environments are an integral part of software development, allowing developers to create stable, scalable, and thoroughly tested applications. By using flavors in Flutter, you can efficiently manage different environments, from development to production, ensuring that each stage of your application is optimized for its intended purpose.

With the Flavor package, you can seamlessly set up, configure, and manage multiple environments within a single Flutter codebase, helping you streamline your development process and improve the quality of your applications. Whether you’re working on a small project or managing a large team, using flavors is a best practice that helps you maintain consistency, reduce errors, and deliver a high-quality user experience.

By effectively leveraging environments and flavors, you can enhance productivity, maintain better version control, and create robust apps that meet user expectations across various stages of development and deployment. Consider implementing flavors in your next Flutter project and experience how it simplifies the development and deployment lifecycle, ultimately providing your users with the best possible experience.

Top comments (0)