英文地址:Separating build environments in Flutter apps
在开发专业的移动应用程度的时候,我们至少需要两个不同的环境:开发环境和生产环境,通过这种方式, 我们可以在开发环境中进行开发及测试新的特性,而不会意外地破坏用户生产环境的任何东西。
样本代码地址:separating_build_environments
最初的应用程序
lib/main.dart是flutter在新建一个项目的时候,为我们生成默认程序的入口文件,生成的模版代码如下:
1 | import 'package:flutter/material.dart'; |
lib/my_home_page.dart:
1 | import 'package:flutter/material.dart'; |
该my_home_page.dart文件是对默认地模版代码文件稍微做了一些修改。
将应用程序分为两个环境
我们当前的应用配置仅是生产环境的,没有方法为生产环境提供环境配置,让我们做些修改,使我们拥有两套不同的环境:development和producation。
这里我们有几个地方想要根据当前的环境来拥有不同的行为:
- 标题栏,生产环境标题是
Build flavors DEV,开发环境是Build flavors。 - 第一个文本控件,开发环境显示文本是
This is the development app,生产环境是the production app。 - 第二个文本控件,开发环境显示文本:
Backend API url is https://dev-api.example.com/,生产环境是Backend API url is https://api.example.com/
我们需要创建一个用于包含所有特定于环境的配置信息的配置类,这是有意义的。
创建配置对象
新建app_config.dart文件,该文件将包含我们所有环境依赖的信息。
在我们这个例子中,将得到这样的结果,如下:
1 | import 'package:meta/meta.dart'; |
你可能正在询问该如何为我们的app提供这些配置信息?你们中的一些人可能早已知晓答案。InheritedWidget使从任务地方获取配置对象变得异常简单。
将AppConfig对象转变为Inherited Widget
为了能够使我们的AppConfig类能够成为Inherited Widget,我们将扩展InheritedWidget类,提供一个静态的of方法来获取该实例,最后重写updateShouldNotify方法。
1 | import 'package:flutter/material.dart'; |
这里有几点需要注意:
- 这个
child参数将会是我们整个MaterialApp实例,我们将包裹我们整个应用在AppConfig对象中。 - 我们创建了一个
of静态方法,这个是InheritedWidget的一般约定,这个方法允许我们无论在哪需要,通过调用AppConfig.of(context)来获取特定环境的配置。 - 在
updateShouldNotify方法中,我只返回false。这个是因为AppConfig在我们创建之后将会不会变化。
接下,让我们为我们的两个环境创建这些文件。
为不同的环境创建启动文件
我们将会为每个环境创建所谓的启动文件,在我们这个例子中,我们仅有两个环境development和producation,这样 我将会新建两个文件main_dev.dart和main_prod.dart。
在每个文件中,我将会用正确的配置数据来创建一个AppConfig类的实例,我们将传入MyApp新的实例到AppConfig控件中,这样我们应用中任何控件能够轻松地获取到这个配置的实例,然后调用runApp,这个我们整个应用程序的入口点。
lib/main_dev.dart:
1 | import 'package:build_flavors/app_config.dart'; |
lib/main_prod.dart:
1 | import 'package:build_flavors/app_config.dart'; |
生产和开发环境的启动文件不同的仅是配置选项的值不同。
lib/main.dart:
1 | import 'package:build_flavors/app_config.dart'; |
在这里,我们仅仅是获取应用的配置实例,并根据当前的环境正确地设置我们的MaterialApp的标题,移除main,因为在对应的启动文件已经包括这个入口函数。
因为我们的整个应用被包裹在了AppConfig控件中(扩展了InheritedWidget),通过调用AppConfig.of(context)就可以从任何地方来获取这个配置信息,这个在控件树更深地节点也是能有效的。
lib/my_home_page.dart:
1 | import 'package:build_flavors/app_config.dart'; |
在不同的环境中运行应用程序
我们可以flutter run命令配合--target或-t(缩写)参数来指定。
在我们这个例子中:
- 运行开发环境的构建,调用
flutter run -t lib/main_dev.dart - 运行生产环境的构建,调用
flutter run -t lib/main_prod.dart
为了创建基于Andriod的发布构建,我可以运行flutter build apk -t lib/main_<environment>.dart,并将根据我们环境得到正确的apk,若是iOS上的发布构建,只需将apk替换成ios。