Flutter开发中,envied是Flutter编译期环境变量代码生成库。它将".env"配置文件转为Dart静态常量,类型安全,编译期校验.简单总结如下:
API:
envied:注解库
envied_generator:代码生成器
build_runner:dart 代码生成工具
场景:
1 多环境配置:开发、测试、生产环境的`baseUrl`、接口域名、开关配置。
2 存储API Key、第三方 SDK密钥。
3 功能开关、全局常量配置。
栗子:
Dart
pubspec.yaml
dependencies:
flutter:
sdk: flutter
envied: ^1.3.2
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^2.4.13
envied_generator: ^1.1.1
Dart
根目录新建.env文件:
BASE_URL=https://dev-api.test.com
APP_NAME=测试APP
DEBUG_MODE=true
API_SECRET=abc123456secret
新建 app_env.dart
Dart
import 'package:envied/envied.dart';
part 'app_env.g.dart';
/// path指向根目录.env文件
@Envied(path: '.env')
abstract class AppEnv {
@EnviedField(varName: 'BASE_URL')
static const String baseUrl = _AppEnv.baseUrl;
@EnviedField(varName: 'APP_NAME')
static const String appName = _AppEnv.appName;
@EnviedField(varName: 'DEBUG_MODE')
static const bool debugMode = _AppEnv.debugMode;
@EnviedField(varName: 'API_SECRET', obfuscate: true)
static final String apiSecret = _AppEnv.apiSecret;
@EnviedField(defaultValue: "10000")
static const int connectTimeout = _AppEnv.connectTimeout;
}
执行生成命令
bash
flutter pub run build_runner build --delete-conflicting-outputs
Dart
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:test_251117/env/app_env.dart';
void main() {
runApp(const EnvTestApp());
}
class EnvTestApp extends StatelessWidget {
const EnvTestApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: AppEnv.appName,
home: Scaffold(
appBar: AppBar(title: Text(AppEnv.appName),),
body: Center(
child: Column(mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("baseUrl:${AppEnv.baseUrl}"),
Text("debugMode:${AppEnv.debugMode}"),
Text("connectTimeout: ${AppEnv.connectTimeout}"),
Text("apiSecret: ${AppEnv.apiSecret}"),
],),
),
),
);
}
}
根目录新建
.env.dev
bash
BASE_URL=https://dev-api.test.com
DEBUG_MODE=true
SENTRY_DSN=dev_sentry_xxxx
.env.prod
Dart
BASE_URL=https://api.online.com
DEBUG_MODE=false
SENTRY_DSN=prod_sentry_yyyy
Dart
import 'package:envied/envied.dart';
part 'config.g.dart';
// ============开发环境配置,使用.env.dev===========
@Envied(path: ".env.dev")
abstract class DevConfig {
@EnviedField(varName: "BASE_URL")
static const String baseUrl = _DevConfig.baseUrl;
@EnviedField(varName: "DEBUG_MODE")
static const bool debugMode = _DevConfig.debugMode;
@EnviedField(varName: "SENTRY_DSN", obfuscate: true)
static final String sentryDsn = _DevConfig.sentryDsn;
}
// ============生产环境配置,使用.env.prod===========
@Envied(path: ".env.prod")
abstract class ProdConfig {
@EnviedField(varName: "BASE_URL")
static const String baseUrl = _ProdConfig.baseUrl;
@EnviedField(varName: "DEBUG_MODE")
static const bool debugMode = _ProdConfig.debugMode;
@EnviedField(varName: "SENTRY_DSN", obfuscate: true)
static final String sentryDsn = _ProdConfig.sentryDsn;
}
执行生成命令
bash
flutter pub run build_runner build --delete-conflicting-outputs
Dart
import 'package:flutter/material.dart';
import '../env/config.dart';
// 编译期选择使用哪一套配置
typedef AppConfig = DevConfig;
// typedef AppConfig = ProdConfig; //切生产环境,切换这里,重新build_runner
void main() {
runApp(const EnvNewApp());
}
class EnvNewApp extends StatelessWidget {
const EnvNewApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("多环境envied Demo")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("baseUrl: ${AppConfig.baseUrl}"),
Text("debug: ${AppConfig.debugMode}"),
Text("sentryDsn: ${AppConfig.sentryDsn}"),
],
),
),
),
);
}
}
注意:
1 修改".env"文件后,必须重新执行 build_runner,否则配置不会更新
2 ".env"、生成的".g.dart"文件加入".gitignore",不要提交密钥到git仓库。