目前,Flutter一共提供了三种运行模式,分别是Debug、Release和Profile模式。其中,Debug模式主要用在软件编写过程当中,Release模式主要用于应用发布过程当中,而Profile模式则主要用于应用性能分析时,每一个模式都有本身特殊的使用场景。下面简介介绍下这几种模式:java
Debug模式
Debug模式又名调试模式,Debug模式能够同时在物理设备、仿真器或者模拟器上运行应用。默认状况下,使用flutter run命令运行应用程序时就是使用的Debug模式。在Debug模式下,全部的断言、服务扩展是开启的,而且在模式对快速开发和运行周期进行了编译优化,当使用调试工具进行代码调试时能够直接链接到应用的进程里。android
Release模式
Release模式又名发布模式,此模式只能在物理设备上运行,不能在模拟器上运行。使用flutter run --release命令运行应用程序时就是使用的Release模式。在Release模式下,断点、调试信息和服务扩展是不可用的,而且Release模式针对快速启动、快速执行和安装包大小进行了优化。json
Profile模式
Profile模式只能在物理设备上运行,不能在模拟器上运行。此模式主要用于应用性能分析,一些应用调试能力是被保留的,目的是分析应用存在的性能问题。Profile模式和Release模式大致相同,不一样点体如今,Profile模式的某些服务扩展是启用的,某些进程调试手段也是开启的。android-studio
在 Debug 模式下,app 能够被安装在物理设备、仿真器或者模拟器上进行调试。在Debug模式下,能够进行以下操做:浏览器
若是是在 Web 平台下的调试模式,能够进行以下操做:并发
默认状况下,运行 flutter run
会使用 Debug 模式,同时 IDE 也支持这些模式。例如,Android Studio 提供了 Run > Debug… 菜单选项,并且在项目面板中还有一个三角形的绿色运行按钮图标 。app
当你想要最大的优化以及最小的占用空间时,就使用 Release 模式来部署 app。 release 模式是不支持模拟器或者仿真器的,使用 Release 模式意味着。框架
对于Web开发来讲,使用 Release 模式意味着。less
在 Profile 模式下,一些调试能力是被保留的,足够分析你的 app 性能。Profile 模式在仿真器和模拟器上是不可用的,由于他们的行为不能表明真实的性能。和 release 相比, profile 模式有如下不一样:async
在 Web 平台使用Profile 模式意味着:
在Flutter应用开发中,有不少工具能够帮助调试 Flutter 应用程序,常见的以下所示。
要调试及分析应用,开发者工具多是你的首选。开发者工具运行在浏览器,支持如下特性:
若是你在Debug 模式 或Profile 模式 运行,那么能够在浏览器打开开发者工具链接到你的应用。开发者工具不能用在 Release 模式 编译的应用,由于调试和分析信息都被删除了。若是你要用开发者工具分析应用,需确保使用 Profile 模式运行应用。
和其余语言同样,Flutter的断点调试支持在 IDE 或编辑器(好比 Android Studio/IntelliJ 和 VS Code)、或者经过编码两种方式。
其中,开发者工具调试器以下图所示。
若是须要,在源代码中设置断点,而后点击工具栏中的 【Debug】 按钮,或选择 【Run】 > 【Debug】便可开启调试功能。
开启调试后,能够在控制台看到以下一些信息。
在进行断点调试时,使用得最多的就是单步调试,三个单步调试按钮在暂停后会变为可用状态。
除此以外,咱们还可使用代码的方式进行断点调试,咱们能够在源代码中使用 debugger()函数来开启断点,当代码运行到此处时就会刮起,以下所示。
import 'dart:developer'; void someFunction(double offset) { debugger(when: offset > 30.0); // ... }
若是你使用的是 Android Studio或者VSCode,那么工具会自带的 Dart 分析器默认会检查代码,并发现可能的错误。若是你使用命令行,则可使用 flutter analyze
命令来检查代码。Dart 分析器很是依赖你在代码中添加的类型注解,以帮助跟踪问题。
另外,咱们可使用flutter analyze --flutter-repo
命令将分析结果打印到控制台上,每次运行这个命名以前,请先运行flutter update-packages
升级最新的包,这样就能够获取最新的依赖包。若是你不这样作,你可能会从dart:ui获得一些错误消息,好比偏移量等。由于执行flutter analysis
命令时并不会主动去拉取依赖。
对于一次性的Dart分析,直接使用flutter analyze --flutter-repo
便可,对于连续分析,则可使用flutter analyze --flutter-repo --watch
命令。若是你想知道多少个成员变量丢失了dartdocs,能够添加一个dartdocs参数。
Flutter inspector 是分析Flutter组件状态树的利器,Flutter使用小部件来控制页面组件到布局的精准控制,Flutter inspector 能够帮助咱们进行以下一些分析。
在调试模式下,咱们点击Android Studio右边Flutter inspector按钮便可开启Flutter inspector分析,Flutter inspector提供了以下的可视化调试工具。
除了上面的功能外,咱们还能够点击【Open DevTools】打开Flutter的调试页面,能够借助它进行不少性能分析,后面会具体介绍。
要收集有关 Flutter 应用程序启动所需时间的详细信息,能够在运行 flutter run 命令时使用 trace-startup 和 profile 选项,以下所示。
flutter run --trace-startup --profile
跟踪输出被保存到 Flutter 工程目录在 build 目录下,一个名为 start_up_info.json 的 JSON 文件中,输出列出了从应用程序启动到这些跟踪事件(以微秒捕获)所用的时间,以下所示。
{ "engineEnterTimestampMicros": 2346054348633, "timeToFrameworkInitMicros": 812748, "timeToFirstFrameRasterizedMicros": 1573154, "timeToFirstFrameMicros": 1221472, "timeAfterFrameworkInitMicros": 408724 }
对应的具体含义以下:
Flutter官方推荐使用Android Studio或VSCode进行应用开发, 和其余语言的调试同样,Dart代码的调试流程也差很少。若是尚未Flutter项目,能够新建一个示例项目。经过单击首先,点击调试图标(Debug-run icon)同时打开调试面板并在控制台中运行应用,首次运行应用是最慢的,应用启动后,界面应该是下面这样的。
而后,咱们在在 counter++ 这一行上添加断点。在应用里,点击 + 按钮(FloatingActionButton,或者简称 FAB)来增长数字,应用会暂停。
你能够 step in/out/over Dart 语句、热重载和恢复执行应用、以及像使用其余调试器同样来使用 Dart 调试器。
Flutter inspector 是一个用来可视化以及查看 Flutter widget 树的工具,提供以下功能:
可使用 Android Studio 窗口右侧的垂直按钮来打开Flutter inspector,以下图所示。
Flutter Outline 是一个可视的显示页面构建方法的功能,注意在构建方法上可能与 widget 树不一样,可使用 Android Studio 窗口右侧的垂直按钮切换 outline 的显示。Tip
: 咱们能够安装一个 Presentation Assistant 插件来辅助咱们进行开发,Presentation Assistant 提供了不少的快捷功能。例如,当焦点在编辑面板中时,输入 command-Shift-A(Mac)或者 shift-control-A(Windows 和 Linux),该插件会同时显示「查找」面板并显示在全部三个平台上执行此操做的提示。
而后在输入框中输入attach关键字,显示以下图。
为了调试原生代码,你须要一个包含 Android 原生代码的应用。在本节中,你将学会如何链接两个调试器到你的应用:
1)Dart 调试器。
2)Android Gradle 调试器。
建立一个基本的 Flutter 应用,而后替换 lib/main.dart 的代码为如下示例代码。
// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'dart:async'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'URL Launcher', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'URL Launcher'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { Future<void> _launched; Future<void> _launchInBrowser(String url) async { if (await canLaunch(url)) { await launch(url, forceSafariVC: false, forceWebView: false); } else { throw 'Could not launch $url'; } } Future<void> _launchInWebViewOrVC(String url) async { if (await canLaunch(url)) { await launch(url, forceSafariVC: true, forceWebView: true); } else { throw 'Could not launch $url'; } } Widget _launchStatus(BuildContext context, AsyncSnapshot<void> snapshot) { if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } else { return Text(''); } } @override Widget build(BuildContext context) { String toLaunch = 'https://flutter.dev'; return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Padding( padding: EdgeInsets.all(16.0), child: Text(toLaunch), ), RaisedButton( onPressed: () => setState(() { _launched = _launchInBrowser(toLaunch); }), child: Text('Launch in browser'), ), Padding(padding: EdgeInsets.all(16.0)), RaisedButton( onPressed: () => setState(() { _launched = _launchInWebViewOrVC(toLaunch); }), child: Text('Launch in app'), ), Padding(padding: EdgeInsets.all(16.0)), FutureBuilder<void>(future: _launched, builder: _launchStatus), ], ), ), ); } }
而后,添加 url_launcher 依赖到 pubspec 文件,并执行 flutter pub get命令拉取依赖包。
name: flutter_app description: A new Flutter application. version: 1.0.0+1 dependencies: flutter: sdk: flutter url_launcher: ^3.0.3 cupertino_icons: ^0.1.2 dev_dependencies: flutter_test: sdk: flutter
点击调试按钮(Debug-run icon)来同时打开调试面板并启动应用,以下图所示。
点击 【Attach debugger to Android process】 按钮,从进程对话框中,你应该能够看到每个设备的入口。选择 show all processes 来显示每一个设备可用的进程。
在调试面板中,你如今应该能够看到一个 Android Debugger 标签页,而后依次选择【app_name】 > 【android】 > 【app】 > 【src】 >【 main】 > 【java】 > 【io.flutter plugins】在项目面板,而后双击 GeneratedProjectRegistrant 在编辑面板中打开 Java 代码,此时Dart 和原生调试器都在与同一个进程交互。