建議使用 flutter_flavor 實現(xiàn)。
多環(huán)境構建配置,在實際的開發(fā)工作中是很有必要的。但是 Flutter 沒有類似 .env 的配置,所以,只能是另辟蹊徑。本文是總結網(wǎng)上一堆經(jīng)驗的一次實踐,上手相對簡單。
![]() |
![]() |
|---|---|
| Production 模式 | Development 模式 |
一、基本操作步驟
- 安裝 Provider 依賴;
- 拆分原有的
main.dart為 2 個部分,一部分為main(),一部分為App()MaterialApp 組件; - 建立對應各個環(huán)境的入口文件,如:
main_prod.dart、main_dev.dart; - 建立環(huán)境配置類
class Env(),給定默認參數(shù),并支持傳入新的配置參數(shù); - 建立狀態(tài)管理類
class StateEnv with ChangeNotifier; - 在對應的入口中使用 Provider 掛載應用,并指定為對應的環(huán)境模式;
- 在頁面中使用
Provider.of<StateEnv>(context)的方式獲取"環(huán)境變量"; - 啟動調(diào)試;
二、詳細步驟
以下是詳細操作步驟:
2.1 安裝 Provider 依賴
Provider 是 flutter 開發(fā)常用的一個狀態(tài)管理庫,參考官方的安裝教程安裝。

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,并粘貼原來實現(xiàn) MaterialApp 的代碼
// import 略···
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
// 組件內(nèi)容略 ···
);
}
}
2.3 建立對應各個環(huán)境的入口文件
為不同的構建環(huán)境創(chuàng)建不同的入口文件,這里暫先創(chuàng)建 2 個入口,分別為 main_prod.dart、main_dev.dart,直接復制原來 main.dart的內(nèi)容到新建的兩個文件。
// ./lib/main_dev.dart
// import 略···
// 這里 import 我們拆分后的 app.dart
import 'app.dart';
void main() {
runApp(App());
}
main_prod.dart 的文件內(nèi)容同上。
2.4 建立環(huán)境配置類 class Env()
我們需要建立一個通用配置文件,如:class Env,并根據(jù)不同的環(huán)境實例化它,如:開發(fā)環(huán)境 new Env( mode: 'dev' ),生產(chǎn)環(huán)境 new Env( mode: 'prod' ) 等。同時,為了統(tǒng)一管理,我還建立了一個環(huán)境枚舉 EnvMode。./lib/utils/env.dart 是我們的環(huán)境配置類,具體文件內(nèi)容如下:
// ./lib/utils/env.dart
// 環(huán)境變量配置
// 環(huán)境標識
enum EnvMode {
PRODUCTION, // 生產(chǎn)環(huán)境
DEVELOPMENT, // 開發(fā)環(huán)境
TEST, // 測試環(huán)境
UAT, // 預發(fā)布環(huán)境
}
class Env {
// 環(huán)境標識
final EnvMode mode;
// 接口參數(shù)
final String api;
// 應用基礎配置
final String appName;
Env({
this.mode = EnvMode.PRODUCTION,
this.api = '',
this.appName = 'Flutter 學習',
}) : super();
}
-
mode是當前環(huán)境標識,可以使用類似Env.mode == EnvMode.DEVELOPMENT的方式判斷當前構建模式; -
api是當前模式使用的數(shù)據(jù)請求接口; -
appName是一個演示變量;
實際開發(fā)中,我們需要根據(jù)環(huán)境配置的內(nèi)容可遠不止這么多。
2.5 建立狀態(tài)管理類
Provider 需要一個支持狀態(tài)響應的類,建立一個 StateEnv 類,內(nèi)容如下:
// ./lib/state/state_env.dart
// 環(huán)境狀態(tài)配置
// import 略 ···
class StateEnv with ChangeNotifier {
// 環(huán)境配置
final Env config;
StateEnv({this.config}) : super();
// 獲取環(huán)境模式
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(
// 支持多個狀態(tài)管理
MultiProvider(
providers: [
// 環(huán)境配置
ChangeNotifierProvider(
create: (BuildContext context) => StateEnv(
config: Env(
mode: EnvMode.DEVELOPMENT, // 使用開發(fā)環(huán)境
api: 'http://127.0.0.1:3000', // 指定該環(huán)境對應的數(shù)據(jù)請求接口
),
),
),
],
child: App(), // App 掛載
),
);
}
2.7 在頁面中讀取配置
其他頁面可以使用 Provider.of<StateEnv>(context, listen: false) 訪問狀態(tài)中的值,如:
// 偽代碼
appBar: AppBar(
title: Text(Provider.of<StateEnv>(context, listen: false).appName),
)
// ./lib/app.dart
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: Provider.of<StateEnv>(context, listen: false).appName,
debugShowCheckedModeBanner: Provider.of<StateEnv>(context).mode == EnvMode.DEVELOPMENT, // 是否顯示右上角 debug 徽標
home: HomePage(),
);
}
}
2.8 啟動調(diào)試
以 IntelliJ IDEA 為例,只需要為不同的入口建立運行配置即可。


