建议使用 flutter_flavor 实现。
多环境构建配置,在实际的开发工作中是很有必要的。但是 Flutter 没有类似 .env 的配置,所以,只能是另辟蹊径。本文是总结网上一堆经验的一次实践,上手相对简单。
Production 模式 | Development 模式 |
一、基本操作步骤
- 安装 Provider 依赖;
- 拆分原有的
main.dart
为 2 个部分,一部分为main()
,一部分为App()
MaterialApp 组件; - 建立对应各个环境的入口文件,如:
main_prod.dart
、main_dev.dart
; - 建立环境配置类
class Env()
,给定默认参数,并支持传入新的配置参数; - 建立状态管理类
class StateEnv with ChangeNotifier
; - 在对应的入口中使用 Provider 挂载应用,并指定为对应的环境模式;
- 在页面中使用
Provider.of
的方式获取"环境变量";(context) - 启动调试;
二、详细步骤
以下是详细操作步骤:
2.1 安装 Provider 依赖
Provider 是 flutter 开发常用的一个状态管理库,参考官方的安装教程安装。
2.2 拆分原有的 main.dart
为了减少冗余代码,我们将拆分原有的 main.dart
为 2 个部分:一部分为 main()
方法,一部分为 App()
MaterialApp 组件;
// 拆分后的 ./lib/main.dart
// import 略···
// 这里 import 我们拆分后的 app.dart
import 'app.dart';
void main() {
runApp(App());
}
// 新建 ./lib/app.dart,并粘贴原来实现 MaterialApp 的代码
// import 略···
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
// 组件内容略 ···
);
}
}
2.3 建立对应各个环境的入口文件
为不同的构建环境创建不同的入口文件,这里暂先创建 2 个入口,分别为 main_prod.dart
、main_dev.dart
,直接复制原来 main.dart
的内容到新建的两个文件。
// ./lib/main_dev.dart
// import 略···
// 这里 import 我们拆分后的 app.dart
import 'app.dart';
void main() {
runApp(App());
}
main_prod.dart
的文件内容同上。
2.4 建立环境配置类 class Env()
我们需要建立一个通用配置文件,如:class Env
,并根据不同的环境实例化它,如:开发环境 new Env( mode: 'dev' )
,生产环境 new Env( mode: 'prod' )
等。同时,为了统一管理,我还建立了一个环境枚举 EnvMode
。./lib/utils/env.dart
是我们的环境配置类,具体文件内容如下:
// ./lib/utils/env.dart
// 环境变量配置
// 环境标识
enum EnvMode {
PRODUCTION, // 生产环境
DEVELOPMENT, // 开发环境
TEST, // 测试环境
UAT, // 预发布环境
}
class Env {
// 环境标识
final EnvMode mode;
// 接口参数
final String api;
// 应用基础配置
final String appName;
Env({
this.mode = EnvMode.PRODUCTION,
this.api = '',
this.appName = 'Flutter 学习',
}) : super();
}
-
mode
是当前环境标识,可以使用类似Env.mode == EnvMode.DEVELOPMENT
的方式判断当前构建模式; -
api
是当前模式使用的数据请求接口; -
appName
是一个演示变量;
实际开发中,我们需要根据环境配置的内容可远不止这么多。
2.5 建立状态管理类
Provider 需要一个支持状态响应的类,建立一个 StateEnv
类,内容如下:
// ./lib/state/state_env.dart
// 环境状态配置
// import 略 ···
class StateEnv with ChangeNotifier {
// 环境配置
final Env config;
StateEnv({this.config}) : super();
// 获取环境模式
EnvMode get mode => this.config.mode;
// 获取接口配置
String get api => this.config.api;
// 获取应用名称
String get appName => this.config.appName;
}
2.6 在对应的入口中使用 Provider 挂载应用;
接下来修改我们的入口文件,按照 Provider 的语法初始化即可。
// ./lib/main_dev.dart
void main() {
// 实例化应用
runApp(
// 支持多个状态管理
MultiProvider(
providers: [
// 环境配置
ChangeNotifierProvider(
create: (BuildContext context) => StateEnv(
config: Env(
mode: EnvMode.DEVELOPMENT, // 使用开发环境
api: 'http://127.0.0.1:3000', // 指定该环境对应的数据请求接口
),
),
),
],
child: App(), // App 挂载
),
);
}
2.7 在页面中读取配置
其他页面可以使用 Provider.of
访问状态中的值,如:
// 伪代码
appBar: AppBar(
title: Text(Provider.of(context, listen: false).appName),
)
// ./lib/app.dart
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: Provider.of(context, listen: false).appName,
debugShowCheckedModeBanner: Provider.of(context).mode == EnvMode.DEVELOPMENT, // 是否显示右上角 debug 徽标
home: HomePage(),
);
}
}
2.8 启动调试
以 IntelliJ IDEA 为例,只需要为不同的入口建立运行配置即可。