Flutter 入门笔记(Part 10) 进阶二

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步:
  1. 扫描工程改动
  2. 增量编译
  3. 推送更新
  4. 代码合并
  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

手机扫码阅读