乐趣区

关于前端:Fluter-应用调试

Flutter 构建模式

目前,Flutter 一共提供了三种运行模式,别离是 Debug、Release 和 Profile 模式。其中,Debug 模式次要用在软件编写过程中,Release 模式次要用于利用公布过程中,而 Profile 模式则次要用于利用性能剖析时,每个模式都有本人非凡的应用场景。上面简介介绍下这几种模式:

Debug 模式
Debug 模式又名调试模式,Debug 模式能够同时在物理设施、仿真器或者模拟器上运行利用。默认状况下,应用 flutter run 命令运行应用程序时就是应用的 Debug 模式。在 Debug 模式下,所有的断言、服务扩大是开启的,并且在模式对疾速开发和运行周期进行了编译优化,当应用调试工具进行代码调试时能够间接连贯到利用的过程里。

Release 模式
Release 模式又名公布模式,此模式只能在物理设施上运行,不能在模拟器上运行。应用 flutter run –release 命令运行应用程序时就是应用的 Release 模式。在 Release 模式下,断点、调试信息和服务扩大是不可用的,并且 Release 模式针对疾速启动、疾速执行和安装包大小进行了优化。

Profile 模式
Profile 模式只能在物理设施上运行,不能在模拟器上运行。此模式次要用于利用性能剖析,一些利用调试能力是被保留的,目标是剖析利用存在的性能问题。Profile 模式和 Release 模式大体雷同,不同点体现在,Profile 模式的某些服务扩大是启用的,某些过程调试伎俩也是开启的。

调试模式

在 Debug 模式下,app 能够被装置在物理设施、仿真器或者模拟器上进行调试。在 Debug 模式下,能够进行如下操作:

  • 断点 是开启的。
  • 服务扩大是开启的。
  • 针对疾速开发和运行周期进行了编译优化(但不是针对执行速度、二进制文件大小或者部署)。
  • 调试开启,相似 开发者工具 等调试工具能够连贯到过程里。

如果是在 Web 平台下的调试模式,能够进行如下操作:

  • 本次构建 没有 最小化资源并且整个构建 没有 优化性能。
  • 为了简化调试,这个 Web 利用应用了 dartdevc 编译器。

默认状况下,运行 flutter run 会应用 Debug 模式,同时 IDE 也反对这些模式。例如,Android Studio 提供了 Run > Debug… 菜单选项,而且在我的项目面板中还有一个三角形的绿色运行按钮图标。

Release 模式

当你想要最大的优化以及最小的占用空间时,就应用 Release 模式来部署 app。release 模式是不反对模拟器或者仿真器的,应用 Release 模式意味着。

  • 断点是不可用的。
  • 调试信息是不可见的。
  • 调试是禁用的。
  • 编译针对疾速启动、疾速执行和小的 package 的大小进行了优化。
  • 服务扩大是禁用的。

对于 Web 开发来说,应用 Release 模式意味着。

  • 这次构建资源曾经被压缩,并且性能得以优化。
  • 这个 Web 利用通过 dart2js 编译器构建,以确保更优良的性能。

Profile 模式

在 Profile 模式下,一些调试能力是被保留的,足够剖析你的 app 性能。Profile 模式在仿真器和模拟器上是不可用的,因为他们的行为不能代表实在的性能。和 release 相比,profile 模式有以下不同:

  • 一些服务扩大是启用的。例如,反对 performance overlay。
  • Tracing 是启用的,一些调试工具,比方 开发者工具 能够连贯到过程里。

在 Web 平台应用 Profile 模式意味着:

  • 资源文件没有被压缩,然而整体性能曾经优化。
  • 这个 Web 利用通过 dart2js 编译器构建。

调试工具

在 Flutter 利用开发中,有很多工具能够帮忙调试 Flutter 应用程序,常见的如下所示。

  • 开发者工具,是一套运行在浏览器的性能及剖析工具。
  • Android Studio/IntelliJ 和 VS Code(借助 Flutter 和 Dart 插件)反对内置的源代码调试器,能够设置断点,单步调试,查看数值。
  • Flutter inspector,是开发者工具提供的 widget 查看器,也可间接在 Android Studio 和 IntelliJ 中应用(借助 Flutter 插件)。查看器能够可视化展示 widget 树,查看单个 widget 及其属性值,开启性能图层,等等。

开发者工具

要调试及剖析利用,开发者工具可能是你的首选。开发者工具运行在浏览器,反对以下个性:

  • 源代码调试器
  • Widget 查看器,展现可视化的 widget 树;“widget select”模式,在利用中抉择一个 widget,会在 widget 树间接定位到它的地位。
  • 内存剖析
  • 工夫线视图,反对跟踪,导入及导出跟踪信息
  • 日志视图

如果你在 Debug 模式 或 Profile 模式 运行,那么能够在浏览器关上开发者工具连贯到你的利用。开发者工具不能用在 Release 模式 编译的利用,因为调试和剖析信息都被删除了。如果你要用开发者工具剖析利用,需确保应用 Profile 模式运行利用。

断点调试

和其余语言一样,Flutter 的断点调试反对在 IDE 或编辑器(比方 Android Studio/IntelliJ 和 VS Code)、或者通过编码两种形式。
其中,开发者工具调试器如下图所示。

如果须要,在源代码中设置断点,而后点击工具栏中的【Debug】按钮,或抉择【Run】>【Debug】即可开启调试性能。

开启调试后,能够在控制台看到如下一些信息。

  • 底部的 Debugger 窗口会显示出堆栈和变量信息。
  • 底部的 Console 窗口会显示具体的日志输入。
  • 调试基于默认的启动配置,如果须要自定义,点击抉择指标下拉按钮,抉择 Edit configuration 进行配置。

在进行断点调试时,应用得最多的就是单步调试,三个单步调试按钮在暂停后会变为可用状态。

  • 应用 Step in 来进入被调用的办法,在遇到办法内的第一行可执行代码时完结。
  • 应用 Step over 间接执行某个办法调用而不进入外部;该按钮在以后办法内按行执行。
  • 应用 Step out 来跳出以后办法,这种形式会间接执行完所有以后办法内的语句。

除此之外,咱们还能够应用代码的形式进行断点调试,咱们能够在源代码中应用 debugger()函数来开启断点,当代码运行到此处时就会刮起,如下所示。

import 'dart:developer';

void someFunction(double offset) {debugger(when: offset > 30.0);
  // ...
}

Dart 分析器

如果你应用的是 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 inspector 是剖析 Flutter 组件状态树的利器,Flutter 应用小部件来管制页面组件到布局的精准管制,Flutter inspector 能够帮忙咱们进行如下一些剖析。

  • 进行布局剖析,了解布局档次
  • 诊断布局问题


在调试模式下,咱们点击 Android Studio 左边 Flutter inspector 按钮即可开启 Flutter inspector 剖析,Flutter inspector 提供了如下的可视化调试工具。

  • Select widget mode:启用此按钮后,抉择组件树的代码会主动跳转到对应的源代码外面。
  • Refresh tree:从新加载最新的组件信息。
  • Slow Animations:加快动画速度,以便进行视觉上的查验。
  • Debug Paint:边框、方向的可视化。
  • Paint Baselines:每个渲染框在它的每个文本基线上画一条线。
  • Repaint Rainbow:查看重绘的重大水平,重大的会被爆红。

除了下面的性能外,咱们还能够点击【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 引擎时
  • 展现利用第一帧时
  • 初始化 Flutter 框架时
  • 实现 Flutter 框架初始化时

应用 Android Studio 进行调试

Flutter 官网举荐应用 Android Studio 或 VSCode 进行利用开发,和其余语言的调试一样,Dart 代码的调试流程也差不多。如果还没有 Flutter 我的项目,能够新建一个示例我的项目。通过单击首先,点击调试图标(Debug-run icon)同时关上调试面板并在控制台中运行利用,首次运行利用是最慢的,利用启动后,界面应该是上面这样的。

而后,咱们在在 counter++ 这一行上增加断点。在利用里,点击 + 按钮(FloatingActionButton,或者简称 FAB)来减少数字,利用会暂停。

你能够 step in/out/over Dart 语句、热重载和复原执行利用、以及像应用其余调试器一样来应用 Dart 调试器。

Flutter inspector

Flutter inspector 是一个用来可视化以及查看 Flutter widget 树的工具,提供如下性能:

  • 理解现有布局
  • 诊断布局问题

能够应用 Android Studio 窗口右侧的垂直按钮来关上 Flutter inspector,如下图所示。

Flutter outline

Flutter Outline 是一个可视的显示页面构建办法的性能,留神在构建办法上可能与 widget 树不同,能够应用 Android Studio 窗口右侧的垂直按钮切换 outline 的显示。

Tip: 咱们能够装置一个 Presentation Assistant 插件来辅助咱们进行开发,Presentation Assistant 提供了很多的快捷性能。例如,当焦点在编辑面板中时,输出 command-Shift-A(Mac)或者 shift-control-A(Windows 和 Linux),该插件会同时显示「查找」面板并显示在所有三个平台上执行此操作的提醒。

而后在输入框中输出 attach 关键字,显示如下图。

应用 Android Gradle 调试

为了调试原生代码,你须要一个蕴含 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 和原生调试器都在与同一个过程交互。

退出移动版