Что такое конфигурация приложения в Flutter?

Ответ

Конфигурация приложения в Flutter — это набор параметров и настроек, которые определяют его поведение в разных средах (разработка, тестирование, продакшн) и на разных платформах.

Основные компоненты конфигурации:

  1. Управление переменными окружения:

    • Флаги --dart-define: Самый распространённый нативный способ.
      flutter run --dart-define=API_BASE=https://api.dev.com --dart-define=ENV=dev
    • Чтение в коде:
      const apiBase = String.fromEnvironment('API_BASE', defaultValue: 'https://default.api.com');
      const isProduction = bool.fromEnvironment('dart.vm.product'); // true в AOT-сборке
  2. Конфигурационные файлы:

    • pubspec.yaml — конфигурация зависимостей, метаданные приложения, assets.
    • Пакеты вроде flutter_dotenv для загрузки переменных из .env-файлов.
  3. Платформо-специфичные настройки:

    • Android: android/app/src/main/AndroidManifest.xml (разрешения, настройки активности).
    • iOS: ios/Runner/Info.plist (разрешения, настройки приложения).
  4. Архитектурные подходы:

    • Создание классов-конфигураций для разных сред.
      
      abstract class AppConfig {
      String get apiBaseUrl;
      bool get enableLogging;
      }

    class DevConfig implements AppConfig { @override String get apiBaseUrl => 'https://dev.api.com'; @override bool get enableLogging => true; }

    class ProdConfig implements AppConfig { @override String get apiBaseUrl => 'https://api.com'; @override bool get enableLogging => false; } // Инициализация в main() в зависимости от флагов

Правильная настройка конфигурации позволяет безопасно управлять API-ключами, эндпоинтами и флагами функциональности.

Ответ 18+ 🔞

Слушай, а вот эта вся тема с конфигурацией в Flutter — она, блядь, как погода в Питере: если её не настроить, будет тебе овердохуища проблем на ровном месте. Представь, ты в продакшн выкатываешь приложение, а оно, сука, стучится на тестовый сервер, где данные одни муляжи. Пиздец, да? Карьера, как тот ледокол «Арктика», накрылась медным тазом.

Так вот, основные киты, на которых это всё держится.

Первое — переменные окружения. Это наш главный инструмент, чтобы не зашивать ключи и адреса прямо в код, как последние распиздяи. Самый нативный способ — это флаги --dart-define. Запускаешь приложение и на лету ему параметры подсовываешь.

flutter run --dart-define=API_BASE=https://api.dev.com --dart-define=ENV=dev

А в коде потом вытаскиваешь эту радость, как из кармана:

const apiBase = String.fromEnvironment('API_BASE', defaultValue: 'https://default.api.com');
const isProduction = bool.fromEnvironment('dart.vm.product'); // true в AOT-сборке

Если переменной нет — сработает дефолтное значение, и приложение не сломается в хлам. Уже спокойнее, да?

Второе — конфигурационные файлы. Ну, pubspec.yaml ты и так знаешь, там зависимости прописаны. Но есть ещё, например, пакет flutter_dotenv. Он позволяет тебе создать файлик .env в корне проекта, написать туда API_KEY=тут_твой_секретный_ключ, и загрузить это всё при старте. Удобно, но нужно следить, чтобы этот файл с ключами случайно в гите не закоммитился. А то выложишь ты всё на всеобщее обозрение, и потом гомосеки-хакеры налетят на твой API. Доверия к такой схеме, блядь, ноль, если не следить.

Третье — платформенные настройки. Это, ёпта, отдельная песня. Ты в Flutter-коде пишешь, а под капотом-то нативные проекты лежат. Для Android это AndroidManifest.xml. Там всякие разрешения на интернет, камеру, геолокацию. Для iOS — Info.plist, там та же история, только с яблочным акцентом. Забыл добавить разрешение — и вся твоя фича с доступом к фото не работает. Пользователь тебе одно звёздочку на маркете и пишет гневный отзыв: «Приложение говно». А всё потому, что в этот plist не залез.

И самое важное — архитектурный подход. Чтобы не было каши, делают так: создают абстрактный класс конфига и от него реализацию для разработки, теста и продакшена.

abstract class AppConfig {
  String get apiBaseUrl;
  bool get enableLogging;
}

class DevConfig implements AppConfig {
  @override String get apiBaseUrl => 'https://dev.api.com';
  @override bool get enableLogging => true; // В деве логируем всё подряд
}

class ProdConfig implements AppConfig {
  @override String get apiBaseUrl => 'https://api.com';
  @override bool get enableLogging => false; // В продакшне тишина
}
// Инициализация в main() в зависимости от флагов

И в самом начале, в main(), в зависимости от флагов, которые мы передали через --dart-define, инициализируем нужную конфигурацию. Получается чисто, опрятно и безопасно. Все ключи и эндпоинты спрятаны, и в репозиторий не утекают. Красота, ядрёна вошь!

Короче, если это не настроить с самого начала, потом будет больно, как вилкой в глаз. А так — живёшь спокойно, и волнение, блядь, на нуле.