8 . 编译模式
- 根据kReleaseMode这个编译常数可以判断出当前是release环境还是debug环境.
- 还可以用个断言判断,release编译的时候会将断言全部移除.
- 通过使用InheritedWidget为应用中可配置部分进行抽象封装(比如接口域名,app名称等),通过配置多入口方式为应用的启动注入配置环境
- 使用kReleaseMode能判断,但是另一个环境的代码虽然不能执行到,但是会被打入二进制包中.会增大包体积,尽量使用断言.或者打release包的时候把kReleaseMode的另一个逻辑注释掉.
if (kReleaseMode) {
//正式环境
text = "release";
} else {
//测试环境 debug
text = "debug";
}
配置一些app的通用配置
///配置抽象
class AppConfig extends InheritedWidget {
//主页标题
final String appName;
//接口域名
final String apiBaseUrl;
AppConfig(
{@required this.appName,
@required this.apiBaseUrl,
@required Widget child})
: super(child: child);
//方便其子Widget在Widget树中找到它
static AppConfig of(BuildContext context) {
return context.inheritFromWidgetOfExactType(AppConfig);
}
//判断是否需要子Widget更新.由于是应用入口,无需更新
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
return false;
}
}
///为不同的环境创建不同的应用入口
//main_dev.dart 这个是正式环境的入口
void main() {
var configuredApp = AppConfig(
appName: 'dev', //主页标题
apiBaseUrl: 'http://dev.example.com/', //接口域名
child: MyApp(),
);
runApp(configuredApp);
}
//main.dart 这个是测试环境的入口
/*void main(){
var configuredApp = AppConfig(){
appName: 'example',//主页标题
apiBaseUrl: 'http://api.example.com/',//接口域名
child: MyApp(),
}
runApp(configuredApp);
}*/
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
var config = AppConfig.of(context);
return MaterialApp(
title: config.appName,
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
var config = AppConfig.of(context);
return Scaffold(
appBar: AppBar(
title: Text(config.appName),
),
body: Center(
child: Text(config.apiBaseUrl),
),
);
}
}
//运行开发环境应用程序
//flutter run -t lib/main_dev.dart
//运行生产环境应用程序
//flutter run -t lib/main.dart
/*
*
//打包开发环境应用程序
flutter build apk -t lib/main_dev.dart
flutter build ios -t lib/main_dev.dart
//打包生产环境应用程序
flutter build apk -t lib/main.dart
flutter build ios -t lib/main.dart
* */
8 . Hot Reload
- Flutter的热重载是基于JIT编译模式的代码增量同步.由于JIT属于动态编译,能够将Dart代码编译成生成中间代码,让Dart VM在运行时解释执行,因此可以通过动态更新中间代码实现增量同步.
- 热重载流程分为5步:
- 扫描工程改动
- 增量编译
- 推送更新
- 代码合并
- Widget树重建
- Flutter接收到代码变更,不会重新启动App,只会触发Widget树的重新绘制..「因此可以保持之前的状态」
- 由于涉及到状态保存与恢复,因此涉及状态兼容和状态初始化的场景,热重载是无法支持的.(比如改动前后Widget状态无法兼容,全局变量与静态属性的更改,main方法里面的更改,initState方法里面更改,枚举和泛型的更改等)
- 如果遇到了热重载无法支持的场景,可以点击工程面板左下角的热重启(Hot Restart)按钮,也很快
9 . 关于调试
- debugPrint函数同样会将消息打印至控制台,但与print不同的是,它提供了定制打印的能力.正式环境的时候将debugPrint函数定义为一个空函数体,就可以一键实现取消打印的功能了.
// 正式环境 将debugPrint指定为空的执行体, 所以它什么也不做
debugPrint = (String message, {int wrapWidth}) {};
debugPrint('test');
//开发环境就需要打印出日志
debugPrint = (String message, {int wrapWidth}) =>
debugPrintSynchronously(message, wrapWidth: wrapWidth);
- 开启Debug Painting,有点像原生的绘制布局边界.
void main() {
//Debug Painting 界面调试工具
//有点像原生的显示布局边界
debugPaintSizeEnabled = true;
runApp(MyApp());
}
-
还可以使用Flutter Inspector去查看更详细的可视化信息.
10 . 常用命令行
阶段 | 子任务 | 命令 |
---|---|---|
工程初始化 | App工程 | flutter create --template=app hello |
工程初始化 | Dart包工程 | flutter create --template=package hello |
工程初始化 | 插件工程 | flutter create --template=plugin hello |
构建 | Debug构建 | flutter build apk --debug flutter build ios --debug |
构建 | Release构建 | flutter build apk --release flutter build ios --release |
构建 | Profile构建 | flutter build apk --profile flutter build ios --profile |
集成原生工程 | 独立App打包 | flutter build apk --release flutter build ios --release |
集成原生工程 | Pod/AAR打包 | flutter build apk --release flutter build ios --release |