Flutter Widget IDE 预览新进展,开始推进落地发布

去年 11 月我们就聊过《Flutter 终于正式规划 IDE Widget 预览支持》,而现在 Widget 预览功能终于开始推进正式落地,并发布了第二版的规划文档

如果你没看到前文,建议看看 :juejin.cn/post/744100...

其实一直以来由于 Flutter 具备 hotload 的能力,所以在 Widget Preview 能力这部分都被认为不是必须的场景,但是基于开发者可以更直观验证一些场景,如屏幕大小、方向、字体大小和区域设置等变量对App 的影响,Widget 预览最终还是被提上了议程。

而这次, Widget Preview 之所以正式开始推进,核心主要依赖两点:

因为 Widget Preview 实际会在 .dart_tool 目录下创建一个名为 widget_preview_scaffold 的 Flutter 项目,这个预览支持项目是一个 Flutter Web App

所以可以理解为,现在大家都是基于 Canvas 的同源 UI ,所以可以用 Web 来实时渲染,从而在 IDE 内实现实时预览。

在预览里,开发者可以和预览进行交互,支持缩放和平移,甚至可以预览动画,不过预览时的实际帧率最高只会是 60 FPS。

而本次 V2 版本规划的预览支持里,主要是新增了 flutter widget-preview 一些列命令,命令负责为项目生成预览脚手架并与预览环境交互支持。

例如,执行 flutter widget-preview start 命令后,就会在 .dart_tool 目录下生成一个预览工程,工程结构大致为:

  • lib/src/widget_preview_rendering.dart:preview scaffold 项目的真正入口点,负责初始化 Dart Tooling Daemon(DTD) 服务和用于渲染 lib/src/generated_preview.dart 中定义的预览的控件
  • lib/src/generated_preview.dart :包含 List<WidgetPreview> previews() 函数,函数最终会将已处理的 WidgetPreview 列表返回到 preview scaffold 用于渲染
  • lib/src/widget_preview.dart:包含 WidgetPreview 类的定义,是一个与 Preview 接近 1:1 映射的数据类,类包括一个 builder 属性,这个属性采用一个闭包返回要预览的 widget
  • lib/src/dtd_services.dart:包含一个 Dart Tooling Daemon (DTD) 服务器连接,为工具提供 Widget 预览服务,并访问其他工具提供的服务(比如和 IDE、分析服务器等交互)。

之后命令会初始化 widget_preview_scaffoldpubspec.yaml,在开发者的项目中添加路径依赖,并列出开发者项目中的资源。

然后在 widget_preview_scaffold 的根目录下生成一个 preview_manifest.json ,包含有关当前 Dart 和 Flutter SDK 版本的信息,以及用户的 pubspec.yaml 的哈希值,这个哈希值用于后续自动对比用户工程的 pubspec 是否发生变化。

接着会使用 package:analyzer 搜索 @Preview() 注解,就如下面代码一样 ,记录需要预览函数名称、库和提供给注解的所有参数等。

最终会根据 analyzer 搜索的结果生成 lib/src/generated_preview.dart

dart 复制代码
@Preview(name: 'Top-level preview')
Widget preview() => const Text('Foo');
​
​
@Preview(name: 'Builder preview')
WidgetBuilder builderPreview() {
  return (BuildContext context) {
    return const Text('Builder');
  };
}
​
​
class MyWidget extends StatelessWidget {
  @Preview(name: 'Constructor preview')
  const MyWidget.preview({super.key});
​
​
  @Preview(name: 'Factory constructor preview')
  factory MyWidget.factoryPreview() => const MyWidget.preview();
​
​
  @Preview(name: 'Static preview')
  static Widget previewStatic() => const Text('Static');
​
​
  @override
  Widget build(BuildContext context) {
    return const Text('MyWidget');
  }
}
​

而一旦用户运行了命令并生成预览脚手架工程之后,它就会被编译并使用提供的 --machine 运行,之后 Flutter 工具将在开发人员的项目目录上初始化一个文件观察器,用于检测源代码的更改,比如:

analyzer 会检测文件中添加或删除的 @Preview() ,必要时重新生成 lib/src/generated_preview.dart 。

另外,flutter widget-preview clean 可以触发删除 .dart_tool/widget_preview_scaffold/ 项目,强制它在下次运行 flutter widget-preview start 时重新生成 。

而针对 Preview 注解也有可定制参数,比如在预览时调节主题,亮度,文本大小等:

js 复制代码
base class Preview {
  /// Annotation used to mark functions that return widget previews.
  const Preview({
    this.name,
    this.width,
    this.height,
    this.textScaleFactor,
    this.wrapper,
    this.theme,
    this.brightness,
  });
​

同时,为了防止用户在整个 widget 预览环境中执行热重启,每个渲染的预览都能够在预览的 widget 上执行 "Soft restart" :

"Soft restart" 只是从一帧的 widget 树中删除预览的 widget,然后再将其重新插入到下一帧:github.com/flutter/flu...

最后,因为最终需要在 IDE 中托管的 webview 中打开预览,需要类似于 Dart/Flutter DevTools 嵌入到 IDE 中的方式,但是由于 DWDS(Web VM 服务实现)需要一个开放的 Chrome 调试端口才能运行,这在 VSCode 等 IDE 中不可用,但是 DWDS 又是热重载的必备支持,所以目前最大的阻碍是:

在没有 Chrome 调试端口的情况下运行 DWDS,同时保持热重载,做到当 DWDS 无法访问 Chrome 调试器时,改为提供一组有限的功能:github.com/dart-lang/w...

其他问题还有比如 dart:io、原生插件等场景需要如何在预览工程处理,但是这些问题都是后话,在 DWDS 适配 IDE场景支持后,IDE 预览就可以基本考虑实验性落地了。

看得出来其实 IDE 预览的话核心其实来自 Flutter Web ,由于 Flutter Web 支持 hotload 之后,用一个阴影工程来做实时预览确实是一个相对低成本的选择,不过真的要完整落地,需要考虑的细节还是很多,其中最重要的莫过于使用过程中的性能影响,如果体验太差,还不如直接 hotload 运行实际。

那么,你会期待或者需要 Flutter 的 IDE Widget 预览吗?

参考链接

相关推荐
草莓熊Lotso3 小时前
Linux 文件描述符与重定向实战:从原理到 minishell 实现
android·linux·运维·服务器·数据库·c++·人工智能
恋猫de小郭3 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
一只大侠的侠7 小时前
Flutter开源鸿蒙跨平台训练营 Day 10特惠推荐数据的获取与渲染
flutter·开源·harmonyos
工程师老罗9 小时前
如何在Android工程中配置NDK版本
android
崔庆才丨静觅9 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606110 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了10 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅10 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅11 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
renke336411 小时前
Flutter for OpenHarmony:色彩捕手——基于HSL色轮与感知色差的交互式色觉训练系统
flutter