【问题标题】:How do I build different versions of my Flutter app for qa/dev/prod?如何为 qa/dev/prod 构建不同版本的 Flutter 应用程序?
【发布时间】:2018-05-06 10:04:44
【问题描述】:

我正在构建一个 Flutter 应用程序,并且我为不同的环境(QA、dev、prod 等)设置了具有不同值的变量。有什么好的方法来组织我的应用,以便我可以轻松地为 QA、开发、生产和其他环境构建?

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    基于 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);
    }
    

    ma​​in_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());
    }
    

    ma​​in_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 runflutter build 在命令行上传递 args,尽管 VS Code 和 Android Studio 都支持将参数传递给main。它还 seems 构建风格作为 main 的命令行 arg 是不合适的,因为 args 可以在构建过程之后传递

    【讨论】:

    • 这应该被标记为正确有用的答案,因为可以更改 IDE 中的其他运行配置以指向使用此解决方案
    • 您将如何使用此解决方案并使您的 API 密钥和配置设置不受源代码控制?
    • 无论如何你可以做这个解决方案并且仍然让flutter run默认启动到开发模式?添加所有额外的命令有点烦人(flutter run -t lib/main_dev.dart
    • 您的 IDE 可能能够为您处理。答案包括如何在 VS Code 中做到这一点。
    • @camillo777 This article 为 Android 解释它,没有特定于 Flutter。
    【解决方案2】:

    现在可以使用

    获取发布和调试模式
    const bool isProduction = bool.fromEnvironment('dart.vm.product');
    

    因为这是一个常数,所以它适用于 tree-shaking。
    像这样的代码

    if(isProduction) {
      // branch 1
    } else {
      // branch 2
    }
    

    根据isProduction,只会将这两个分支之一包含到生产代码中

    【讨论】:

    • 这似乎是一个很好的解决方案,是否有原因它没有得到更多的牵引力作为答案?
    • 可能是因为这是一个较老的问题,而我在 3 个月前才发布了答案。
    • 如果在整个项目中使用,我认为它可能容易出错。最好仅在初始化应用程序时使用它。
    • @droid8421 你真的否决了我的回答,因为你认为我建议的代码不应该出现在你的应用程序中吗??
    • 这个值不错,但仍然无法满足问题,因为它说dev/qa/prod。此值仅标识dev/qaprod
    【解决方案3】:

    一种方法:在项目的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/…
    • @Simon 也许该问题已由构建过程修复,例如flutter build apk -t lib/main_debug.dart?
    • @Jacob 我承诺修复它不适用于 iOS。我相信它在 dev 分支中。
    • @Simon 正如你所说,本机端(在我的情况下为 Android Studio)既不需要 main_dev.dart 也不需要 main_prod.dart,它仍然运行“主”文件,所以我该如何告诉 Android Studio按下“播放”按钮时,哪个文件在 Flutter 端运行?提前致谢
    【解决方案4】:

    从 Flutter 1.17 开始,您可以使用 --dart-define 来构建具有不同编译时间变量的应用程序。它适用于 Dart 和原生层。例如,在 dart 中,您可以使用 String.fromEnvironment 获得这些值。这样,您就不需要拥有大量或入口点并公开您的环境凭据

    这里有一篇解释更多的文章https://link.medium.com/ibuTsWHrk6

    【讨论】:

    • 这个解决方案很棒。本文展示了如何为每个环境创建多个构建,并且还使 iOS 配置方面的配置更加容易,以使用相同的代码生成多个应用程序。
    【解决方案5】:
    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.
    }
    

    【讨论】:

    • 我坚信对于大多数情况而言,这是最简单、最优雅的解决方案。
    【解决方案6】:

    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"));
         }
    }
    

    【讨论】:

      【解决方案7】:

      您只需实现构建变体即可。

      在安卓中:

      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 中处理这些环境?
      • 我们是否有类似的东西将 .qa 或 .dev 附加到 iOS 中的包标识符
      • @siva kumar 但我们无法通过颤振构建flutter build apk --qa
      • @siva kumar 您使用什么命令生成“qa”apk 版本?
      • @SaahithyanVigneswaran flutter build apk --flavor qa
      【解决方案8】:

      更简洁的方法是通过构建风味

      举个简单的例子,如果你想为你的“开发”构建应用一个不同的应用 ID,你可以在 gradle 文件中包含这个:

      flavorDimensions "version"
      productFlavors {
          dev {
              applicationIdSuffix ".dev"
              versionNameSuffix "-dev"
          }
      }
      

      阅读更多关于 gradle 构建变体配置here


      现在您可以使用命令行运行此构建变体:

      flutter run --flavor dev
      

      如果您使用的是 Android Studio,您也可以在 Run 配置中设置构建变体:

      blog 上阅读有关 iOS 配置的更多信息。还有关于 build flavours 的官方 Flutter 文档。

      【讨论】:

        【解决方案9】:

        在项目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';
            }
          }
        }
        

        【讨论】:

          猜你喜欢
          • 2013-07-09
          • 1970-01-01
          • 2018-06-18
          • 2012-06-02
          • 1970-01-01
          • 1970-01-01
          • 2019-05-19
          • 2022-07-04
          • 1970-01-01
          相关资源
          最近更新 更多