为什么在 Flutter 中使用 `@immutable`?你可能忽略了这个细节

14 阅读2分钟

在日常的 Flutter 开发中,我们常常会在一些类上看到 @immutable 这个注解,尤其是在定义 WidgetState 时。但它到底有什么作用?加和不加有什么区别?今天我们就来深入聊聊这个小细节背后的大意义。

一、什么是 @immutable

在 Dart 中,@immutable 是一个用于标记类为不可变的注解。加上它之后,意味着这个类的所有字段都必须是 final,一旦创建实例就不能再修改。

它来自 Flutter 的 foundation.dart

import 'package:flutter/foundation.dart';

@immutable
class Person {
  final String name;
  final int age;

  const Person({required this.name, required this.age});
}

二、加与不加的区别

对比项加了 @immutable没加
字段是否必须 final✅ 是❌ 否
静态分析器警告✅ 有❌ 无
是否支持 const 构造✅ 支持❌ 不支持
适合状态管理✅ 更安全❌ 容易出 Bug
性能优化(const 复用)✅ 是❌ 否

三、不加会怎样?

看个例子👇:

class User {
  final String name;
  int age; // ⚠️ 非 final 字段

  User({required this.name, required this.age});
}

虽然代码能编译运行,但这违背了“不可变”的设计理念。当你在状态管理(如 Bloc、Provider)中复用这个对象时,如果只修改了字段值,但没有创建新的对象,Flutter 是无法感知变化的,界面可能就不会更新!

四、为什么 Flutter 推荐使用不可变类?

Flutter 的核心机制是「重建界面」。每次状态变化时,Flutter 会比较前后的 Widget 是否发生变化,如果是同一个实例对象,Flutter 默认认为没有变化。

这就是为什么状态类和 Widget 类通常都使用不可变写法:

@immutable
class CounterState {
  final int count;
  const CounterState(this.count);
}

如果你把 count 改为普通变量,虽然看起来“更方便”,但 UI 很可能不刷新,调试成本也会飙升。

五、开发建议

  • 所有 Widget 和状态类建议加上 @immutable
  • 配合 const 使用,提升性能
  • 如果你在使用 freezed,它默认会自动加上
  • 不要为了图方便让状态对象可变,这是隐藏的 bug 温床

六、总结

在 Flutter 中使用 @immutable,并不是“可有可无”的细节,而是一个保障代码可维护性、可预测性和性能优化的重要机制。

你可能在不知不觉中忽略了它,但一旦项目复杂起来,状态不同步、UI 不刷新、调试困难等问题就会找上门来。

从今天起,为你的状态类、数据类加上 @immutable 吧,养成良好的编码习惯,未来你会感谢现在的自己!

如果这篇文章对你有帮助,欢迎点赞、在看和转发。关注我,一起写出更优雅的 Flutter 代码!

📮 微信公众号:OldBirds