Flutter Tools的调试

5,820 阅读2分钟

前言

flutter tools中集成了很多强大的命令,比如:

  • flutter create: 创建app、module、plugin、package
  • flutter build: 构建apk、aar等
  • flutter run: 运行 要想弄清楚各种命令背后的原理,一方面可以看静态代码,另一方面则是动态调试。

导入flutter tools源码

我们知道flutter tools是用dart实现的,其源码位于path/to/flutter/packages/flutter_tools。 用Android Studio打开该项目。

设置断点

很多程序的调试原理都类似,都是通过在启动对应的程序时,传入一些调试相关的参数,让对应的进程启动后进行等待,等到Debugger进程attach到该进程后继续运行。

Flutter Tools本质上是一个dart程序,它的调试是Dart虚拟机支持的。

具体到Android Studio上,有两种配置方式:

  1. Dart Command Line App
  2. Dart Remote Debug

Dart Command Line App

这一种比较简单,新建一个Dart Command Line App的Configuration。

Edit Configurations -》New -》 Dart Command Line App。如果所示:

Dart file指向flutter_tools.dart,这是入口文件。 Programma arguments填上要运行的命令,比如 create flutter_app. 然后在其中的main方法上添加断点,然后点击调试按钮,如图所示

接下来程序会在断点处停下来,如图所示

可以看到args正是我们设置的参数。

Dart Remote Debug

新建一个Configuration。 Edit Configurations -》New -》 Dart Remote Debug -》 输入Host为127.0.0.1,端口号为12345,如果所示:

IDE中提示我们使用--enable-vm-service:12345 --pause_isolates_on_start来启动dart虚拟机。这两个参数是告诉Dart虚拟机开启调试端口12345,并在启动后暂停等待。 我们可以通过设置FLUTTER_TOOL_ARGS环境变量来设置参数

 export FLUTTER_TOOL_ARGS="--enable-vm-service:12345 --pause_isolates_on_start"

然后运行flutter命令

flutter create flutter_app

此时会输出如下信息:

Observatory listening on http://127.0.0.1:12345/-7kH8m0Z5Ys=/

同样设好断点,然后点击调试按钮,结果却发现attach不上,错误信息如图所示

Failed to connect to the VM observatory service: java.io.IOException: Failed to connect: ws://127.0.0.1:12345/ws
Caused by: de.roderick.weberknecht.WebSocketException: error while creating socket to ws://127.0.0.1:12345/ws
Caused by: java.net.ConnectException: Connection refused (Connection refused)

发现url对不上,Dart虚拟机等待的url后面多了个-7kH8m0Z5Ys= 经过查资料,发现这是一种认证码,是为了安全原因,防止应用被远程调试。可以通过参数--disable-service-auth-codes进行关闭。

 export FLUTTER_TOOL_ARGS="--enable-vm-service:12345 --pause_isolates_on_start --disable-service-auth-codes"

然后重新运行flutter create flutter_app命令,这次成功了,如图所示

除了通过FLUTTER_TOOL_ARGS环境变量,还可以直接运行dart命令。

dart --enable-vm-service:12345 --pause_isolates_on_start --disable-service-auth-codes /Users/szw/dev_tools/flutter/packages/flutter_tools/bin/flutter_tools.dart create flutter_app

其实FLUTTER_TOOL_ARGS也是flutter命令传给dart的。 flutter脚本的路径为flutter/bin/flutter,其中的最后一行就是

"$DART" --packages="$FLUTTER_TOOLS_DIR/.packages" $FLUTTER_TOOL_ARGS "$SNAPSHOT_PATH" "$@"

总结

本文提到的方法不止适用于flutter tools,也适用于其他的dart应用。另外其他语言的调试基本也都类似,大家可以举一反三。