Harmony 状态管理

🔄 状态管理对比学习指南 - @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()

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容