🔄 状态管理对比学习指南 - @State装饰器
适合 iOS/Flutter/Android 开发者快速理解鸿蒙状态管理
一、@State 基础对比
鸿蒙 (ArkTS)
@Component
struct Counter {
@State count: number = 0 // 组件内状态
build() {
Column() {
Text(`Count: ${this.count}`)
Button('增加')
.onClick(() => {
this.count++ // 修改会自动触发UI刷新
})
}
}
}
SwiftUI
struct Counter: View {
@State private var count = 0 // 组件内状态
var body: some View {
VStack {
Text("Count: \(count)")
Button("增加") {
count += 1 // 修改会自动触发UI刷新
}
}
}
}
Flutter
class Counter extends StatefulWidget {
@override
_CounterState createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int count = 0; // 组件内状态
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Count: $count'),
ElevatedButton(
onPressed: () {
setState(() { // 需要手动调用setState触发刷新
count++;
});
},
child: Text('增加'),
),
],
);
}
}
Android (Jetpack Compose)
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) } // 组件内状态
Column {
Text("Count: $count")
Button(onClick = { count++ }) { // 修改会自动触发UI刷新
Text("增加")
}
}
}
二、状态装饰器全面对比
| 功能 |
鸿蒙 |
SwiftUI |
Flutter |
Android (Compose) |
| 组件内状态 |
@State |
@State |
setState() |
remember + mutableStateOf |
| 单向传递 |
@Prop |
传参 |
构造函数 |
参数传递 |
| 双向绑定 |
@Link |
@Binding |
回调函数 |
MutableState |
| 观察对象 |
@Observed |
@ObservedObject |
Provider |
collectAsState() |
| 跨组件共享 |
@Provide/@Consume |
@EnvironmentObject |
InheritedWidget |
CompositionLocal |
三、详细对比示例
1. 组件内状态 (@State)
鸿蒙
@Component
struct Profile {
@State name: string = '张三'
@State age: number = 25
@State isActive: boolean = true
build() {
Column() {
Text(`姓名: ${this.name}`)
Text(`年龄: ${this.age}`)
Toggle(this.isActive)
.onChange((isOn) => {
this.isActive = isOn
})
}
}
}
SwiftUI
struct Profile: View {
@State private var name = "张三"
@State private var age = 25
@State private var isActive = true
var body: some View {
VStack {
Text("姓名: \(name)")
Text("年龄: \(age)")
Toggle("激活", isOn: $isActive)
}
}
}
Flutter
class Profile extends StatefulWidget {
@override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
String name = '张三';
int age = 25;
bool isActive = true;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('姓名: $name'),
Text('年龄: $age'),
Switch(
value: isActive,
onChanged: (value) {
setState(() => isActive = value);
},
),
],
);
}
}
Android
@Composable
fun Profile() {
var name by remember { mutableStateOf("张三") }
var age by remember { mutableStateOf(25) }
var isActive by remember { mutableStateOf(true) }
Column {
Text("姓名: $name")
Text("年龄: $age")
Switch(checked = isActive, onCheckedChange = { isActive = it })
}
}
2. 父子组件传值 (@Prop)
鸿蒙
// 子组件
@Component
struct Child {
@Prop message: string // 单向传递,父→子
build() {
Text(this.message)
}
}
// 父组件
@Component
struct Parent {
@State msg: string = 'Hello'
build() {
Column() {
Child({ message: this.msg }) // 传递给子组件
Button('修改')
.onClick(() => {
this.msg = 'World' // 子组件会自动更新
})
}
}
}
SwiftUI
// 子组件
struct Child: View {
let message: String // 单向传递
var body: some View {
Text(message)
}
}
// 父组件
struct Parent: View {
@State private var msg = "Hello"
var body: some View {
VStack {
Child(message: msg)
Button("修改") {
msg = "World"
}
}
}
}
Flutter
// 子组件
class Child extends StatelessWidget {
final String message;
Child({required this.message});
@override
Widget build(BuildContext context) {
return Text(message);
}
}
// 父组件
class Parent extends StatefulWidget {
@override
_ParentState createState() => _ParentState();
}
class _ParentState extends State<Parent> {
String msg = 'Hello';
@override
Widget build(BuildContext context) {
return Column(
children: [
Child(message: msg),
ElevatedButton(
onPressed: () => setState(() => msg = 'World'),
child: Text('修改'),
),
],
);
}
}
3. 双向绑定 (@Link)
鸿蒙
// 子组件
@Component
struct InputField {
@Link text: string // 双向绑定
build() {
TextInput({ text: this.text })
.onChange((value) => {
this.text = value // 修改会同步到父组件
})
}
}
// 父组件
@Component
struct Parent {
@State content: string = ''
build() {
Column() {
InputField({ text: $content }) // $表示双向绑定
Text(`内容: ${this.content}`)
}
}
}
SwiftUI
// 子组件
struct InputField: View {
@Binding var text: String // 双向绑定
var body: some View {
TextField("输入", text: $text)
}
}
// 父组件
struct Parent: View {
@State private var content = ""
var body: some View {
VStack {
InputField(text: $content) // $表示双向绑定
Text("内容: \(content)")
}
}
}
Flutter (需要回调)
// 子组件
class InputField extends StatelessWidget {
final String text;
final Function(String) onChanged;
InputField({required this.text, required this.onChanged});
@override
Widget build(BuildContext context) {
return TextField(
controller: TextEditingController(text: text),
onChanged: onChanged,
);
}
}
// 父组件
class Parent extends StatefulWidget {
@override
_ParentState createState() => _ParentState();
}
class _ParentState extends State<Parent> {
String content = '';
@override
Widget build(BuildContext context) {
return Column(
children: [
InputField(
text: content,
onChanged: (value) => setState(() => content = value),
),
Text('内容: $content'),
],
);
}
}
4. 跨组件状态共享 (@Provide/@Consume)
鸿蒙
// 祖先组件
@Component
struct GrandParent {
@Provide theme: string = 'light' // 提供状态
build() {
Column() {
Parent()
Button('切换主题')
.onClick(() => {
this.theme = this.theme === 'light' ? 'dark' : 'light'
})
}
}
}
// 后代组件(可以跨多层)
@Component
struct Child {
@Consume theme: string // 消费状态
build() {
Text(`当前主题: ${this.theme}`)
}
}
SwiftUI
// 定义环境对象
class ThemeManager: ObservableObject {
@Published var theme = "light"
}
// 祖先组件
struct GrandParent: View {
@StateObject var themeManager = ThemeManager()
var body: some View {
VStack {
Parent()
.environmentObject(themeManager) // 注入
Button("切换主题") {
themeManager.theme = themeManager.theme == "light" ? "dark" : "light"
}
}
}
}
// 后代组件
struct Child: View {
@EnvironmentObject var themeManager: ThemeManager // 获取
var body: some View {
Text("当前主题: \(themeManager.theme)")
}
}
Flutter (Provider)
// 定义模型
class ThemeModel extends ChangeNotifier {
String _theme = 'light';
String get theme => _theme;
void toggle() {
_theme = _theme == 'light' ? 'dark' : 'light';
notifyListeners();
}
}
// 祖先组件
class GrandParent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => ThemeModel(),
child: Column(
children: [
Parent(),
Consumer<ThemeModel>(
builder: (_, model, __) => ElevatedButton(
onPressed: model.toggle,
child: Text('切换主题'),
),
),
],
),
);
}
}
// 后代组件
class Child extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = context.watch<ThemeModel>().theme;
return Text('当前主题: $theme');
}
}
四、状态类型对比
| 类型 |
鸿蒙 |
SwiftUI |
Flutter |
Android |
| 基本类型 |
@State count: number |
@State var count: Int |
int count + setState
|
mutableStateOf(0) |
| 对象类型 |
@State user: User |
@State var user: User |
User user + setState
|
mutableStateOf(User()) |
| 数组类型 |
@State list: Item[] |
@State var list: [Item] |
List<Item> + setState
|
mutableStateOf(listOf()) |
| 可观察对象 |
@Observed user: User |
@ObservedObject var user |
Provider<User> |
collectAsState() |
五、关键区别
鸿蒙 vs SwiftUI
| 对比项 |
鸿蒙 |
SwiftUI |
| 语法 |
@State count: number = 0 |
@State var count = 0 |
| 双向绑定 |
@Link + $变量
|
@Binding + $变量
|
| 跨组件 |
@Provide/@Consume |
@EnvironmentObject |
| 观察对象 |
@Observed/@ObjectLink |
@ObservedObject |
鸿蒙 vs Flutter
| 对比项 |
鸿蒙 |
Flutter |
| 状态定义 |
@State count = 0 |
int count = 0 |
| 触发刷新 |
自动 |
手动调用 setState
|
| 组件类型 |
统一 @Component
|
StatelessWidget/StatefulWidget |
| 跨组件 |
@Provide/@Consume |
Provider/InheritedWidget |
鸿蒙 vs Android
| 对比项 |
鸿蒙 |
Android |
| 状态定义 |
@State count = 0 |
remember { mutableStateOf(0) } |
| 触发刷新 |
自动 |
自动 |
| 双向绑定 |
@Link |
MutableState |
| 跨组件 |
@Provide/@Consume |
CompositionLocal |
六、最佳实践对比
✅ 推荐做法
| 场景 |
鸿蒙 |
SwiftUI |
Flutter |
Android |
| 简单状态 |
@State |
@State |
setState |
remember |
| 父子传值 |
@Prop |
参数传递 |
构造函数 |
参数传递 |
| 双向绑定 |
@Link |
@Binding |
回调函数 |
MutableState |
| 全局状态 |
@Provide/@Consume |
@EnvironmentObject |
Provider |
CompositionLocal |
❌ 避免的做法
| 平台 |
避免操作 |
| 鸿蒙 |
在 @Prop 上直接修改值 |
| SwiftUI |
在子视图修改传入的值(非 @Binding) |
| Flutter |
忘记调用 setState
|
| Android |
在 Composable 外部修改状态 |
七、快速记忆口诀
鸿蒙状态记心间:
@State 组件内,修改自动刷界面
@Prop 父传子,单向流动不变更
@Link 双向绑,父子同步两边连
@Provide/@Consume 跨组件,祖先后代共分享
对比SwiftUI:
@State ≈ @State
@Prop ≈ let参数
@Link ≈ @Binding
@Provide/@Consume ≈ @EnvironmentObject
对比Flutter:
@State ≈ setState
@Prop ≈ final参数
@Link ≈ 回调函数
@Provide/@Consume ≈ Provider
对比Android:
@State ≈ remember + mutableStateOf
@Prop ≈ 参数传递
@Link ≈ MutableState
@Provide/@Consume ≈ CompositionLocal
八、完整示例:计数器应用
鸿蒙
@Component
struct CounterApp {
@State count: number = 0
build() {
Column() {
Text(`计数: ${this.count}`)
.fontSize(24)
Row() {
Button('-')
.onClick(() => this.count--)
Button('+')
.onClick(() => this.count++)
}
}
}
}
SwiftUI
struct CounterApp: View {
@State private var count = 0
var body: some View {
VStack {
Text("计数: \(count)")
.font(.title)
HStack {
Button("-") { count -= 1 }
Button("+") { count += 1 }
}
}
}
}
Flutter
class CounterApp extends StatefulWidget {
@override
_CounterAppState createState() => _CounterAppState();
}
class _CounterAppState extends State<CounterApp> {
int count = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('计数: $count', style: TextStyle(fontSize: 24)),
Row(
children: [
ElevatedButton(
onPressed: () => setState(() => count--),
child: Text('-'),
),
ElevatedButton(
onPressed: () => setState(() => count++),
child: Text('+'),
),
],
),
],
);
}
}
Android
@Composable
fun CounterApp() {
var count by remember { mutableStateOf(0) }
Column {
Text("计数: $count", fontSize = 24.sp)
Row {
Button(onClick = { count-- }) { Text("-") }
Button(onClick = { count++ }) { Text("+") }
}
}
}
九、总结对照表
| 需求 |
鸿蒙 |
SwiftUI |
Flutter |
Android |
| 组件内状态 |
@State |
@State |
setState() |
remember |
| 父传子 |
@Prop |
参数 |
构造函数 |
参数 |
| 子传父 |
@Link |
@Binding |
回调 |
回调 |
| 跨组件 |
@Provide/@Consume |
@EnvironmentObject |
Provider |
CompositionLocal |
| 对象观察 |
@Observed |
@ObservedObject |
Provider |
collectAsState |
📌 核心记忆: 鸿蒙的 @State = SwiftUI的 @State = Android的 remember,都是自动触发UI刷新的组件内状态。Flutter最特殊,需要手动调用 setState()。