使用 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 总是先吼我的开发者。

参考资料

相关推荐
星秋Eliot11 小时前
认识 Flutter
flutter
tangweiguo0305198711 小时前
Flutter 根据后台配置动态生成页面完全指南
flutter
stringwu11 小时前
Flutter开发者必备:状态管理Bloc的实用详解
前端·flutter
humiaor1 天前
Flutter之riverpod状态管理详解
flutter·provider·riverpod
浮生若茶80881 天前
创建Flutter项目的两种方式
flutter
RaidenLiu1 天前
Riverpod 3:组合与参数化的进阶实践
前端·flutter
ideal树叶1 天前
Provider中的watch、read、Consumer、ChangeNotifierProvider、ValueNotifierProvider
flutter
勤劳打代码1 天前
独辟蹊径 —— NSIS 自定义 EXE 应用名称
windows·flutter
阿笑带你学前端1 天前
当手机遇上电视:Flutter实现局域网遥控输入的奇妙之旅
前端·flutter
早起的年轻人1 天前
Flutter 3.35.2 以上版本中 数字转字符串的方法指南
前端·flutter