【发布时间】:2018-05-06 10:04:44
【问题描述】:
我正在构建一个 Flutter 应用程序,并且我为不同的环境(QA、dev、prod 等)设置了具有不同值的变量。有什么好的方法来组织我的应用,以便我可以轻松地为 QA、开发、生产和其他环境构建?
【问题讨论】:
我正在构建一个 Flutter 应用程序,并且我为不同的环境(QA、dev、prod 等)设置了具有不同值的变量。有什么好的方法来组织我的应用,以便我可以轻松地为 QA、开发、生产和其他环境构建?
【问题讨论】:
基于 Seth 的想法,这里有一个示例,它设置了一个全局代表 BuildEnvironment,名为 env。
env.dart
import 'package:meta/meta.dart';
enum BuildFlavor { production, development, staging }
BuildEnvironment get env => _env;
BuildEnvironment _env;
class BuildEnvironment {
/// The backend server.
final String baseUrl;
final BuildFlavor flavor;
BuildEnvironment._init({this.flavor, this.baseUrl});
/// Sets up the top-level [env] getter on the first call only.
static void init({@required flavor, @required baseUrl}) =>
_env ??= BuildEnvironment._init(flavor: flavor, baseUrl: baseUrl);
}
main_dev.dart
import 'package:flutter/material.dart';
import 'env.dart';
import 'app.dart';
void main() {
BuildEnvironment.init(
flavor: BuildFlavor.development, baseUrl: 'http://dev.example.com');
assert(env != null);
runApp(App());
}
main_prod.dart
import 'package:flutter/material.dart';
import 'env.dart';
import 'app.dart';
void main() {
BuildEnvironment.init(
flavor: BuildFlavor.production, baseUrl: 'http://example.com');
assert(env != null);
runApp(App());
}
env.dart 以公开env 变量。使用target 选项运行和构建应用程序。
flutter run -t lib/main_dev.dart
flutter build -t lib/main_dev.dart
要与 VS Code 集成,请定义启动配置:
.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "development",
"program": "lib/main_dev.dart",
"request": "launch",
"type": "dart"
},
{
"name": "production",
"program": "lib/main_prod.dart",
"request": "launch",
"type": "dart"
}
]
}
我最初打算使用传递给 Dart 的 main 函数的命令行参数,但我认为目前不能使用 flutter run 或 flutter build 在命令行上传递 args,尽管 VS Code 和 Android Studio 都支持将参数传递给main。它还 seems 构建风格作为 main 的命令行 arg 是不合适的,因为 args 可以在构建过程之后传递。
【讨论】:
flutter run默认启动到开发模式?添加所有额外的命令有点烦人(flutter run -t lib/main_dev.dart)
现在可以使用
获取发布和调试模式const bool isProduction = bool.fromEnvironment('dart.vm.product');
因为这是一个常数,所以它适用于 tree-shaking。
像这样的代码
if(isProduction) {
// branch 1
} else {
// branch 2
}
根据isProduction,只会将这两个分支之一包含到生产代码中
【讨论】:
dev/qa/prod。此值仅标识dev/qa 或prod。
一种方法:在项目的lib/ 目录中创建不同的main_<environment>.dart 文件。
每个main_<environment>.dart 都包含特定于环境的配置/值(例如不同的数据库名称等)。然后每个main_<environment>.dart 导入实际的应用程序库并运行应用程序,传入环境的值/配置。
然后,选择要构建的.dart 文件:flutter run -t lib/main_debug.dart
【讨论】:
FlutterView的本机端仍然使用runFromBundle和“main”。 github.com/flutter/engine/blob/master/shell/platform/android/io/…
flutter build apk -t lib/main_debug.dart?
从 Flutter 1.17 开始,您可以使用 --dart-define 来构建具有不同编译时间变量的应用程序。它适用于 Dart 和原生层。例如,在 dart 中,您可以使用 String.fromEnvironment 获得这些值。这样,您就不需要拥有大量或入口点并公开您的环境凭据
这里有一篇解释更多的文章https://link.medium.com/ibuTsWHrk6
【讨论】:
import 'package:flutter/foundation.dart';
并使用以下 const 值:
if (kReleaseMode) {
// App is running in release mode.
} else if (kProfileMode) {
// App is running in profile mode.
} else if (kDebugMode) {
// App is running in debug mode.
} else if (kIsWeb) {
// App is running on the web.
}
【讨论】:
2019 年 7 月更新:
我写了一个集成了 Flutter Global Config 的 Package。
EZ Flutter 是小部件、包和许多有用的东西的集合,混合在一个小框架中。目的是从头开始提供标准功能。
Github:https://github.com/Ephenodrom/EZ-Flutter
dependencies:
ez_flutter: ^0.2.0
查看文档如何使用不同的配置。
https://github.com/Ephenodrom/EZ-Flutter/blob/master/documentation/APPLICATION_SETTINGS.md
++++ 旧答案 ++++
附加信息:
我遇到了同样的问题,并使用了 Seth Ladd 建议的解决方案。因此,我还需要为每个应用程序版本(dev / prod)进行不同的配置,并且我不想将配置写入 main_dev.dart 或 main_prod.dart 文件中。
我编写了一个简单的 Flutter 包,用于处理分离的配置文件并在应用启动时加载它们。然后,您的应用中的每一行代码都可以使用该配置。
https://github.com/Ephenodrom/Flutter-Global-Config
如何使用它:
在assets/cfg/$file.json下创建一个json文件
将资产/cfg 添加到您的 pubspec.yaml
在应用启动时加载不同的配置文件:
import 'package:flutter/material.dart';
import 'package:global_configuration/global_configuration.dart';
void main() async{
await GlobalConfiguration().loadFromAsset("app_settings");
await GlobalConfiguration().loadFromAsset("env_dev_settings");
runApp(MyApp());
}
class MyApp extends StatelessWidget {
...
}
在您的应用中使用配置:
import 'package:flutter/material.dart';
import 'package:global_configuration/global_configuration.dart';
class CustomWidget extends StatelessWidget {
CustomWiget(){
// Access the config in the constructor
print(GlobalConfiguration().getString("key1"); // prints value1
}
@override
Widget build(BuildContext context) {
// Access the config in the build method
return new Text(GlobalConfiguration().getString("key2"));
}
}
【讨论】:
您只需实现构建变体即可。
在安卓中:
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.release
}
debug{
applicationIdSuffix ".dev"
signingConfig signingConfigs.debug
}
qa{
applicationIdSuffix ".qa"
signingConfig signingConfigs.qa
}
}
productFlavors {
dev {
dimension "app"
resValue "string", "app_name", "xyz Dev"
applicationId "com.xyz.dev"
}
prod {
dimension "app"
resValue "string", "app_name", "xyz"
}
}
在 iOS 中:
通过选择项目->运行器->配置添加一个来添加配置
【讨论】:
flutter build apk --qa
更简洁的方法是通过构建风味。
举个简单的例子,如果你想为你的“开发”构建应用一个不同的应用 ID,你可以在 gradle 文件中包含这个:
flavorDimensions "version"
productFlavors {
dev {
applicationIdSuffix ".dev"
versionNameSuffix "-dev"
}
}
阅读更多关于 gradle 构建变体配置here。
现在您可以使用命令行运行此构建变体:
flutter run --flavor dev
如果您使用的是 Android Studio,您也可以在 Run 配置中设置构建变体:
在blog 上阅读有关 iOS 配置的更多信息。还有关于 build flavours 的官方 Flutter 文档。
【讨论】:
在项目app_environment.dart 的根目录下创建一个文件。使用 foundation.dart 包中的 kReleaseMode 变量检查生产模式。
import 'package:flutter/foundation.dart';
class AppEnvironment {
String getApiURL() {
if (kReleaseMode) {
return 'PROD_API_URL';
} else {
return 'STAGING_API_URL';
}
}
}
【讨论】: