使用 Flutter Lints 提升你的 Flutter 代码:更整洁、更安全、更快速的应用

好的,如果让我以一个真正的、亲自动手的 Flutter 开发者身份,跟其他开发者聊聊,我会这样重新组织这段话------可能不完美,但绝对实用。

说实话,没有什么比丑陋、不一致的代码 ,以及那些不知怎么就溜到测试环境的**"隐形"Bug** 更让人丧失动力的了。如果你和哪怕一个队友一起捣鼓过一个中等规模的 Flutter 代码库,你肯定懂我在说什么:合并地狱、莫名其妙的警告 ,还有大家为了一个该死的组件格式怎么写而争论不休。我吃过太多亏了,所以我知道------如果你想让你的 Flutter 应用保持整洁,不变成一堆烂摊子,那么 lints 绝不是可选项。它们就像你平时忘了系的安全带......直到你撞车。

咱们今天就来聊聊真正实用的 Flutter lints 设置------不是那种"加个包就完事"的敷衍内容。我分享的这些,是实实在在帮助我(大部分时候)保持理智的方法,尤其是在我需要在不同功能间切换、审查同事的 PR,或者在昏昏欲睡的周五晚上努力不搞砸 CI 的时候。


我的 Flutter Lint 实战流程

说实话,这些命令已经刻在我肌肉记忆里了。如果你还没开始用它们,那你很可能错过了连自己都不知道的 Bug。


flutter analyze

这绝对是我的首选 。我总是会运行它,甚至在代码推送之前也不例外。为啥?因为它能捕获那些"卧槽"的瞬间------未使用的变量、意外的动态类型、缺失的 Key,以及各种各样的问题。如果我有一周没跑这个命令,我肯定会后悔。这是发现明显问题最简单、最快捷的方法。


dart fix --dry-run

你可以把它想象成你的代码算命师。它会告诉你 Dart 会自动修复哪些内容,但并不会真的改动你的代码,这样你就不必盲目地信任一个"黑箱"。我通常会在进行任何大型重构之前,先用它来快速预览一下潜在的影响。


dart format .

没人希望审查一个包含 200 行"格式化修改"的 PR,那简直是噪音。我每次都会运行这个命令,有时甚至会把它放到 pre-commit hook 里。是的,它会覆盖所有内容,但这正是它的目的:现在我们所有的代码看起来真正对齐、保持一致了。


dart fix --apply

一旦我对 dart fix --dry-run 建议的修改感到满意,我就会让它执行。这个命令一口气修复了大量烦人的问题。老实说,光是这一个命令就为我节省了大量手动查找和修正 lint 警告的时间。它能极大地提升效率。


像真实项目一样设置 Lints

步骤 1: 添加 lints 包

别想太多------直接用官方的就行:

yaml 复制代码
dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^6.0.0 # 坚持经常检查最新版本。 pub.dev是你的好朋友.

然后,运行 flutter pub get。很简单。


步骤 2: 实际使用 analysis_options.yaml

这里就是你制定规则的地方了。有些人可能直接复制粘贴 README 里的内容,但如果你想以后少点麻烦,最好根据你的团队(或你自己)的习惯来调整它。

如果你的项目根目录下没有 analysis_options.yaml,那就加一个。

先从基础配置开始,然后逐步加入你认为必不可少的规则:

yaml 复制代码
include: package:flutter_lints/flutter.yaml

analyzer:
  language:
    strict-casts: true
    strict-inference: true
    strict-raw-types: true
linter:
  rules:
    prefer_const_constructors: true
    prefer_final_locals: true
    require_trailing_commas: true
    always_declare_return_types: true
    use_super_parameters: true
    avoid_unnecessary_containers: true
    use_key_in_widget_constructors: true
    unawaited_futures: true
    avoid_catching_errors: true
    # 根据你的"感觉"来添加、删除或注释掉任何规则。

专业提示: 如果你对什么是"干净的代码"有自己的看法,那么 analysis_options.yaml 这个文件才是你和团队应该"争论"的地方,而不是在第四次合并冲突之后才来吵。


我实际使用的 Lint 规则(及原因)

Lint 规则多如牛毛。这里我将我总是启用的那些规则(以及我为什么费心启用它们)进行了分类,分为"让你的应用更不容易崩溃"和"让你的代码更不容易让队友讨厌你"两类。其中大部分都救过我,或者至少让我避免了令人尴尬的 PR 评论。

安全与健壮性规则

  • use_key_in_widget_constructors (在 widget 构造函数中使用 key): 相信我,如果你曾因为缺少 key 导致列表视图出现奇怪的问题,你绝对不会想再调试那种鬼东西。这条规则会强制你在自定义组件中总是添加 key: 参数。我以前也忽视这个,直到有一次一个 UI 状态 Bug 花了我一个小时才追踪到。
  • discarded_futures & unawaited_futures (被丢弃的 Future & 未等待的 Future): Flutter 是一个异步的世界。如果你忘记 await 一个 Future(或者只是让它悬着),你可能会遇到 UI 更新只完成一半、静默失败,或者你以为已经完成的后台操作其实并没有。这些规则会指出你没有正确处理 Future 的问题------说真的,它们救我免于生产环境的 Bug。
  • avoid_catching_errors (避免捕获 Error): 有时你就是想随便加个 try/catch 然后继续,但千万别捕获 Dart 的 Error!这条规则确保你不会吞掉编程错误(比如 NoSuchMethodError),这些错误是设计成大声崩溃的,这样你才会真正去修复它们。
  • no_logic_in_create_state (createState 中不含逻辑): 我以前习惯把设置代码都扔进 createState,但后来我的热重载就开始出问题,我还会无缘无故地丢失状态。经验教训啊,保持那个方法干净。
  • use_build_context_synchronously (同步使用 BuildContext): 经典的 Flutter 陷阱:你执行一个异步调用,然后尝试在 await 之后使用 context------砰,报错。这条规则可以保护你免受此害,说实话,我真希望它能早点出现。
  • avoid_unnecessary_containers (避免不必要的 Container): 如果你像我一样,有时只是随便用 Container 包裹一些东西。结果发现,这会让你的 Widget 树变得混乱,有时甚至会影响性能。这条规则会轻轻地拍你的手,然后说:"嘿,你真的需要这个吗?"
  • enable_null_safety (启用空安全): 空安全现在基本上是 Flutter 的标配了,但如果你的代码库比较老旧或者混杂,一定要仔细检查是否启用了它。与空相关的 Bug 绝对是最糟糕的。
  • avoid_returning_null_for_void (避免为 void 返回 null): Dart 的 void 函数不需要返回 null。这条规则有助于让你的代码更符合惯用法,并且对任何阅读代码的人(包括未来的你)来说都更不容易混淆。

代码质量与可维护性规则

  • file_names (文件命名): 大胆发言:我不会总是在处理旧代码时强制使用 snake_case,但如果你从头开始,那就直接用吧。一致的文件命名很枯燥,但非常值得。
  • prefer_const_constructors (偏好使用 const 构造函数): 这是最简单的性能提升。Flutter 对 const 非常着迷。如果能用,就用它------它有助于构建优化,让应用更流畅。
  • prefer_const_literals_to_create_immutables (偏好使用 const 字面量创建不可变对象): 同理:所有东西都 const 化,即使是你的列表和映射。如果它们不需要改变,就让它们变成 const
  • prefer_final_fields / prefer_final_locals (偏好使用 final 字段 / 偏好使用 final 局部变量): 每次我把一个变量设为可变时,总会有人(有时是我自己)不小心在后来改变它。把所有东西都 final。这会让你的代码库更可预测,错误也少得多。
  • always_use_package_imports (总是使用 package 导入): 相对路径导入没问题------直到你开始移动文件。到处使用 package: 导入帮我避免了太多愚蠢的合并冲突和构建失败。
  • require_trailing_commas (要求尾随逗号): 小细节,但它让每个 git diff 都更容易阅读,而且自动格式化工具也能更好地工作。
  • camel_case_types (驼峰式类型命名): 类和枚举应该使用 CamelCase。如果你曾经读过别人的代码,却分不清什么是类什么是方法,你就会明白为什么了。
  • constant_identifier_names (常量标识符命名): 为你的常量选择一种风格(camelCaseUPPER_SNAKE_CASE)并坚持下去。没人想在同一个文件里看到 Myvar 旁边是 MY_CONST
  • curly_braces_in_flow_control_structures (流控制结构中使用大括号): 这条规则是一个经典的 Bug 防御者:即使是单行的 if 和循环,也要始终使用大括号。它能帮你避免那些咬过每个写 C 风格代码的人的"悬空 else"Bug。
  • always_declare_return_types (总是声明返回类型): 不要指望 Dart 分析器能完全理解你的意图。明确地声明------这会让阅读和重构代码的痛苦大大减少。
  • no_leading_underscores_for_local_identifiers (局部标识符不带前导下划线): 下划线是为私有成员保留的,而不是随便给局部变量用。这能让你的代码不那么混乱。
  • unnecessary_constructor_name (不必要的构造函数名): Dart 允许你命名构造函数,但如果你只是重复类名,那就没必要了。这条规则会标记出那些无意义的构造函数。
  • empty_catches (空 catch 块): 如果你捕获了一个异常却什么都不做,那你只是在为未来制造一堆麻烦。处理它,或者至少把它记录下来。
  • unnecessary_null_checks (不必要的空检查): Dart 的空安全功能非常智能。如果你看到代码中到处都是 !?,这条规则可以帮助你清理这些多余的检查。

真心话:Lints 是一种文化,不是一份清单

采纳 lints 更多地是为了在三个月后不至于讨厌自己的(或团队的)代码,而不是简单地遵循"规则"。从基础开始,添加那些对你的项目真正重要的规则,并不断调整。相信我,你会有更多时间去构建酷炫的功能,而不是去修复愚蠢的 Bug 或者争论空格和制表符。

如果你在每次提交前都没有运行这些检查?那就等着瞧吧------你会以一种痛苦的方式学到教训的(我就经历过)。

祝你编程愉快,愿你的构建总是绿色。

------一个曾经搞砸过不少 Flutter 项目,但至少 lints 总是先吼我的开发者。

参考资料

相关推荐
梦想改变生活16 小时前
《Flutter篇第一章》基于GetX 和 Binding、Dio 实现的 Flutter UI 架构
flutter·ui·架构
耳東陈20 小时前
[重磅发布] Flutter Chen Generator 必备脚本工具
flutter
亿刀21 小时前
【学习VPN之路】NET技术
android·flutter
浅蓝色21 小时前
Flutter平台判断问题,并适配鸿蒙
flutter
RaidenLiu21 小时前
Skia与Impeller的对比测试
flutter
mobsmobs2 天前
Flutter开发环境搭建与工具链
android·flutter·ios·android studio·xcode
Bryce李小白2 天前
Flutter 主流 UI 框架总结归纳
flutter·ui
谕酱2 天前
flutter_ume停更了,那我就自己写一个flutter_mana
flutter·dart
顾林海2 天前
Dart 异步编程之 Future 详解
flutter·面试·dart