基础入门 Flutter for OpenHarmony:深入理解 StatelessWidget 与 StatefulWidget

🎯欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
🔍 本文将带你深入理解 Flutter 中两种最基础的 Widget 类型------StatelessWidget 和 StatefulWidget,掌握 Flutter 状态管理的核心概念。


一、Widget 体系概述

在 Flutter 中,一切皆 Widget。Widget 是 Flutter 应用的构建块,用于描述 UI 的配置信息。Flutter 提供了两种基础的 Widget 类型:StatelessWidget(无状态组件)和 StatefulWidget(有状态组件)。

🎯 为什么需要区分两种 Widget?

理解 StatelessWidget 和 StatefulWidget 的区别,是掌握 Flutter 开发的关键一步。这两种 Widget 的设计理念不同,适用于不同的场景。

StatelessWidget 的特点:

  • 状态不可变,一旦创建就保持不变
  • 性能高效,不需要维护状态
  • 适用于静态内容、纯展示组件
  • 重建时完全重新创建

StatefulWidget 的特点:

  • 状态可变,可以响应用户交互和数据变化
  • 通过 State 对象管理状态
  • 适用于需要动态更新的组件
  • 重建时复用 State 对象

💡 核心思想:StatelessWidget 就像一张静态图片,而 StatefulWidget 就像一个可以变化的动画。选择合适的 Widget 类型,可以让代码更简洁、性能更优。


二、StatelessWidget 无状态组件

2.1 基本概念

StatelessWidget 是最简单的 Widget 类型,它的父类是 Widget。StatelessWidget 的配置在创建时确定,之后不会改变。

dart 复制代码
class MyTextWidget extends StatelessWidget {
  final String text;
  final Color color;

  const MyTextWidget({
    super.key,
    required this.text,
    this.color = Colors.black,
  });

  @override
  Widget build(BuildContext context) {
    return Text(
      text,
      style: TextStyle(color: color),
    );
  }
}

2.2 工作原理

StatelessWidget 的生命周期非常简单:

  1. 创建:构造函数被调用,初始化所有 final 字段
  2. 构建build() 方法被调用,返回 Widget 树
  3. 重建:如果父组件重建,StatelessWidget 会被完全重新创建
dart 复制代码
// 第一次创建
MyTextWidget(text: 'Hello', color: Colors.blue)

// 父组件重建时,创建新的实例
MyTextWidget(text: 'Hello', color: Colors.blue) // 新实例

💡 小贴士:StatelessWidget 的所有字段都应该是 final,确保状态不可变。如果需要修改数据,请使用 StatefulWidget。

2.3 适用场景

StatelessWidget 适用于以下场景:

场景 示例 说明
纯文本展示 Text、RichText 内容固定,不需要交互
图标显示 Icon、Image 静态资源或固定 URL
布局容器 Container、Padding 仅用于布局,不保存状态
样式组件 Card、Divider 纯视觉组件
数据展示 列表项、信息卡片 数据由父组件传入

2.4 最佳实践

dart 复制代码
// ✅ 好的实践:所有字段都是 final
class UserCard extends StatelessWidget {
  final String name;
  final String email;
  final String avatarUrl;

  const UserCard({
    super.key,
    required this.name,
    required this.email,
    required this.avatarUrl,
  });

  @override
  Widget build(BuildContext context) {
    return Card(
      child: ListTile(
        leading: CircleAvatar(
          backgroundImage: NetworkImage(avatarUrl),
        ),
        title: Text(name),
        subtitle: Text(email),
      ),
    );
  }
}

// ❌ 不好的实践:字段不是 final
class BadWidget extends StatelessWidget {
  String text; // 应该是 final

  BadWidget(this.text); // 应该使用 const

  @override
  Widget build(BuildContext context) {
    return Text(text);
  }
}

三、StatefulWidget 有状态组件

3.1 基本概念

StatefulWidget 是可以保存状态并响应变化的 Widget。它由两个类组成:StatefulWidget 本身和对应的 State 类。

dart 复制代码
class CounterWidget extends StatefulWidget {
  final int initialValue;

  const CounterWidget({
    super.key,
    this.initialValue = 0,
  });

  @override
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  late int _counter;

  @override
  void initState() {
    super.initState();
    _counter = widget.initialValue;
  }

  void _increment() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('计数: $_counter'),
        ElevatedButton(
          onPressed: _increment,
          child: const Text('增加'),
        ),
      ],
    );
  }
}

3.2 工作原理

StatefulWidget 的生命周期比 StatelessWidget 复杂得多:

  1. 创建 StatefulWidget:调用构造函数,创建 Widget 实例
  2. 创建 State :调用 createState(),创建对应的 State 对象
  3. 初始化状态 :调用 initState(),初始化状态数据
  4. 构建 UI :调用 build(),返回 Widget 树
  5. 状态更新 :调用 setState(),标记需要重建
  6. 重建 UI :再次调用 build(),更新 UI
  7. 销毁 :调用 dispose(),清理资源

💡 核心要点:StatefulWidget 本身是不可变的,状态存储在 State 对象中。当 Widget 重建时,State 对象会被复用,而不是重新创建。

3.3 生命周期详解

dart 复制代码
class LifecycleWidget extends StatefulWidget {
  const LifecycleWidget({super.key});

  @override
  State<LifecycleWidget> createState() => _LifecycleWidgetState();
}

class _LifecycleWidgetState extends State<LifecycleWidget> {
  @override
  void initState() {
    super.initState();
    print('initState: 组件初始化');
    // 初始化状态、订阅事件流等
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print('didChangeDependencies: 依赖变化');
    // 当依赖的 InheritedWidget 变化时调用
  }

  @override
  void didUpdateWidget(LifecycleWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    print('didUpdateWidget: Widget 更新');
    // 当父组件重建并传入新的配置时调用
  }

  @override
  void setState(VoidCallback fn) {
    super.setState(fn);
    print('setState: 状态更新,触发重建');
    // 调用此方法会触发 build 方法重新执行
  }

  @override
  void deactivate() {
    super.deactivate();
    print('deactivate: 组件停用');
    // 当组件从树中移除时调用,但可能被重新插入
  }

  @override
  void dispose() {
    super.dispose();
    print('dispose: 组件销毁');
    // 清理资源、取消订阅等
  }

  @override
  Widget build(BuildContext context) {
    print('build: 构建 UI');
    return const Text('生命周期示例');
  }
}

3.4 生命周期方法对照表

方法 调用时机 用途
createState() 创建 StatefulWidget 时 创建 State 对象
initState() State 对象插入树中时 初始化状态、订阅事件
didChangeDependencies() 依赖变化时 响应 InheritedWidget 变化
didUpdateWidget() 父组件重建时 处理配置变化
setState() 状态更新时 标记需要重建
deactivate() 从树中移除时 临时停用(可能重新插入)
dispose() 永久移除时 清理资源

3.5 setState 的正确使用

setState 是 StatefulWidget 中最重要的方法,用于触发 UI 重建。

dart 复制代码
class CounterWidget extends StatefulWidget {
  const CounterWidget({super.key});

  @override
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  // ✅ 正确用法:在 setState 中修改状态
  void _increment() {
    setState(() {
      _counter++;
    });
  }

  // ❌ 错误用法:不使用 setState
  void _badIncrement() {
    _counter++; // 不会触发重建
  }

  // ❌ 错误用法:在 build 中调用 setState
  @override
  Widget build(BuildContext context) {
    setState(() {
      // 这会导致无限循环!
    });
    return Text('$_counter');
  }

  // ✅ 正确用法:异步操作后更新状态
  Future<void> _loadData() async {
    final data = await fetchData();
    setState(() {
      _counter = data;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('计数: $_counter'),
        ElevatedButton(
          onPressed: _increment,
          child: const Text('增加'),
        ),
      ],
    );
  }
}

⚠️ 重要提示setState 会在下一个帧触发 build 方法,因此不能在 build 方法中调用 setState,否则会导致无限循环。


四、何时使用哪种 Widget

4.1 选择标准

选择 StatelessWidget 还是 StatefulWidget,可以遵循以下标准:

使用 StatelessWidget 的情况:

  • Widget 的配置在创建后不会改变
  • Widget 不需要响应任何用户交互
  • Widget 的数据完全来自父组件
  • Widget 纯粹用于展示,不保存任何状态

使用 StatefulWidget 的情况:

  • Widget 需要响应用户交互(点击、输入等)
  • Widget 需要根据时间或其他条件更新
  • Widget 需要保存和修改内部状态
  • Widget 需要管理动画效果

4.2 决策流程图

复制代码
Widget 需要改变吗?
    ├─ 否 → StatelessWidget
    └─ 是 → 需要响应交互吗?
              ├─ 否 → 考虑数据能否由父组件管理
              └─ 是 → StatefulWidget

4.3 实际案例分析

案例 1:纯展示卡片 → StatelessWidget

dart 复制代码
class ProductCard extends StatelessWidget {
  final String name;
  final double price;
  final String imageUrl;

  const ProductCard({
    super.key,
    required this.name,
    required this.price,
    required this.imageUrl,
  });

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Column(
        children: [
          Image.network(imageUrl),
          Text(name),
          Text('¥$price'),
        ],
      ),
    );
  }
}

案例 2:可点击的点赞按钮 → StatefulWidget

dart 复制代码
class LikeButton extends StatefulWidget {
  const LikeButton({super.key});

  @override
  State<LikeButton> createState() => _LikeButtonState();
}

class _LikeButtonState extends State<LikeButton> {
  bool _isLiked = false;
  int _likeCount = 0;

  void _toggleLike() {
    setState(() {
      _isLiked = !_isLiked;
      _likeCount += _isLiked ? 1 : -1;
    });
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _toggleLike,
      child: Row(
        children: [
          Icon(
            _isLiked ? Icons.favorite : Icons.favorite_border,
            color: _isLiked ? Colors.red : Colors.grey,
          ),
          const SizedBox(width: 8),
          Text('$_likeCount'),
        ],
      ),
    );
  }
}

五、StatefulWidget 的高级用法

5.1 使用 widget 访问配置

State 类可以通过 widget 属性访问对应的 StatefulWidget 的配置。

dart 复制代码
class ConfigurableWidget extends StatefulWidget {
  final String title;
  final Color backgroundColor;

  const ConfigurableWidget({
    super.key,
    required this.title,
    required this.backgroundColor,
  });

  @override
  State<ConfigurableWidget> createState() => _ConfigurableWidgetState();
}

class _ConfigurableWidgetState extends State<ConfigurableWidget> {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: widget.backgroundColor,
      child: Text(widget.title),
    );
  }
}

5.2 处理配置变化

当父组件传入新的配置时,可以通过 didUpdateWidget 响应变化。

dart 复制代码
class UpdatingWidget extends StatefulWidget {
  final String message;

  const UpdatingWidget({
    super.key,
    required this.message,
  });

  @override
  State<UpdatingWidget> createState() => _UpdatingWidgetState();
}

class _UpdatingWidgetState extends State<UpdatingWidget> {
  late String _displayMessage;

  @override
  void initState() {
    super.initState();
    _displayMessage = widget.message;
  }

  @override
  void didUpdateWidget(UpdatingWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.message != oldWidget.message) {
      setState(() {
        _displayMessage = '更新: ${widget.message}';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Text(_displayMessage);
  }
}

5.3 Keys 的使用

Keys 用于标识 Widget,帮助 Flutter 知道哪些 Widget 应该保留,哪些应该重建。

dart 复制代码
class KeyedListItem extends StatelessWidget {
  final String id;
  final String title;

  const KeyedListItem({
    super.key,
    required this.id,
    required this.title,
  });

  @override
  Widget build(BuildContext context) {
    return ListTile(
      key: ValueKey(id), // 使用 ValueKey
      title: Text(title),
    );
  }
}

💡 小贴士:在列表中使用唯一且稳定的 Key 可以显著提升性能,避免不必要的重建。

5.4 释放资源

dispose 方法中清理资源,避免内存泄漏。

dart 复制代码
class ResourceWidget extends StatefulWidget {
  const ResourceWidget({super.key});

  @override
  State<ResourceWidget> createState() => _ResourceWidgetState();
}

class _ResourceWidgetState extends State<ResourceWidget> {
  late StreamSubscription _subscription;
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    // 创建资源
    _subscription = someStream.listen((data) {
      setState(() {});
    });
    _controller = AnimationController(
      duration: const Duration(seconds: 1),
      vsync: this,
    );
  }

  @override
  void dispose() {
    // 释放资源
    _subscription.cancel();
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

六、性能优化

6.1 避免不必要的重建

使用 const 构造函数可以避免不必要的 Widget 重建。

dart 复制代码
// ❌ 不好的实践
class BadWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('标题'), // 每次都会创建新的实例
        Text('内容'),
      ],
    );
  }
}

// ✅ 好的实践
class GoodWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Column(
      children: [
        Text('标题'), // 使用 const,只创建一次
        Text('内容'),
      ],
    );
  }
}

6.2 使用 RepaintBoundary

RepaintBoundary 可以创建独立的绘制层,避免整个子树重绘。

dart 复制代码
class OptimizedWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const StaticHeader(), // 静态内容
        RepaintBoundary(
          child: const AnimatedContent(), // 动画内容独立重绘
        ),
      ],
    );
  }
}

6.3 分离状态管理

将状态从 UI 中分离,使代码更易于维护和测试。

dart 复制代码
// 状态管理类
class CounterState {
  int value = 0;
  void increment() => value++;
}

// UI 组件
class CounterWidget extends StatefulWidget {
  const CounterWidget({super.key});

  @override
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  final CounterState _state = CounterState();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('计数: ${_state.value}'),
        ElevatedButton(
          onPressed: () {
            setState(() {
              _state.increment();
            });
          },
          child: const Text('增加'),
        ),
      ],
    );
  }
}

七、完整示例代码

下面是一个完整的 Flutter 应用示例,展示 StatelessWidget 和 StatefulWidget 的各种用法。

dart 复制代码
import 'package:flutter/material.dart';

void main() {
  runApp(const StateDemo());
}

class StateDemo extends StatelessWidget {
  const StateDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'StatelessWidget & StatefulWidget 演示',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.dark(
          primary: const Color(0xFF6366F1),
          secondary: const Color(0xFF8B5CF6),
          surface: const Color(0xFF1E293B),
          background: const Color(0xFF0F172A),
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      home: const StatePage(),
    );
  }
}

class StatePage extends StatelessWidget {
  const StatePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFF0F172A),
      body: SafeArea(
        child: SingleChildScrollView(
          padding: const EdgeInsets.all(20),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // 标题区域
              Container(
                padding: const EdgeInsets.all(24),
                decoration: BoxDecoration(
                  gradient: LinearGradient(
                    begin: Alignment.topLeft,
                    end: Alignment.bottomRight,
                    colors: [
                      const Color(0xFF6366F1).withOpacity(0.2),
                      const Color(0xFF8B5CF6).withOpacity(0.2),
                    ],
                  ),
                  borderRadius: BorderRadius.circular(20),
                  border: Border.all(
                    color: Colors.white.withOpacity(0.1),
                  ),
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text(
                      '🔍 State Management',
                      style: TextStyle(
                        fontSize: 28,
                        fontWeight: FontWeight.bold,
                        color: Colors.white,
                        letterSpacing: 0.5,
                      ),
                    ),
                    const SizedBox(height: 8),
                    Text(
                      '深入理解 StatelessWidget 与 StatefulWidget',
                      style: TextStyle(
                        fontSize: 14,
                        color: Colors.white.withOpacity(0.7),
                        height: 1.5,
                      ),
                    ),
                  ],
                ),
              ),

              const SizedBox(height: 32),

              // Stateless 示例
              _buildSection(
                title: 'StatelessWidget 示例',
                icon: Icons.widgets_outlined,
                color: Colors.blue,
                child: _buildDemoCard([
                  const StaticTextWidget(text: '静态文本组件'),
                  const SizedBox(height: 16),
                  const UserCardWidget(
                    name: '张三',
                    email: 'zhangsan@example.com',
                  ),
                ]),
              ),

              const SizedBox(height: 24),

              // Stateful 示例
              _buildSection(
                title: 'StatefulWidget 示例',
                icon: Icons.refresh,
                color: Colors.green,
                child: _buildDemoCard([
                  const CounterWidget(),
                  const SizedBox(height: 16),
                  const LikeButtonWidget(),
                ]),
              ),

              const SizedBox(height: 24),

              // 生命周期示例
              _buildSection(
                title: '生命周期示例',
                icon: Icons.timeline,
                color: Colors.purple,
                child: _buildDemoCard([
                  const LifecycleWidget(),
                ]),
              ),

              const SizedBox(height: 24),

              // 性能优化示例
              _buildSection(
                title: '性能优化示例',
                icon: Icons.speed,
                color: Colors.orange,
                child: _buildDemoCard([
                  const PerformanceWidget(),
                ]),
              ),

              const SizedBox(height: 80),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildSection({
    required String title,
    required IconData icon,
    required Color color,
    required Widget child,
  }) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          children: [
            Container(
              padding: const EdgeInsets.all(8),
              decoration: BoxDecoration(
                color: color.withOpacity(0.2),
                borderRadius: BorderRadius.circular(10),
              ),
              child: Icon(icon, color: color, size: 20),
            ),
            const SizedBox(width: 12),
            Text(
              title,
              style: const TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.w600,
                color: Colors.white,
              ),
            ),
          ],
        ),
        const SizedBox(height: 12),
        child,
      ],
    );
  }

  Widget _buildDemoCard(List<Widget> children) {
    return Container(
      width: double.infinity,
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: Colors.white.withOpacity(0.03),
        borderRadius: BorderRadius.circular(16),
        border: Border.all(
          color: Colors.white.withOpacity(0.05),
        ),
      ),
      child: Column(
        children: children,
      ),
    );
  }
}

// StatelessWidget 示例
class StaticTextWidget extends StatelessWidget {
  final String text;

  const StaticTextWidget({super.key, required this.text});

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.blue.withOpacity(0.1),
        borderRadius: BorderRadius.circular(12),
      ),
      child: Text(
        text,
        style: const TextStyle(
          fontSize: 16,
          color: Colors.white,
        ),
      ),
    );
  }
}

class UserCardWidget extends StatelessWidget {
  final String name;
  final String email;

  const UserCardWidget({
    super.key,
    required this.name,
    required this.email,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.blue.withOpacity(0.1),
        borderRadius: BorderRadius.circular(12),
      ),
      child: Row(
        children: [
          CircleAvatar(
            backgroundColor: Colors.blue.withOpacity(0.3),
            child: Text(
              name[0],
              style: const TextStyle(color: Colors.white),
            ),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  name,
                  style: const TextStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                  ),
                ),
                const SizedBox(height: 4),
                Text(
                  email,
                  style: TextStyle(
                    fontSize: 14,
                    color: Colors.white.withOpacity(0.7),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

// StatefulWidget 示例
class CounterWidget extends StatefulWidget {
  const CounterWidget({super.key});

  @override
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  void _increment() {
    setState(() {
      _counter++;
    });
  }

  void _decrement() {
    setState(() {
      _counter--;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: Colors.green.withOpacity(0.1),
        borderRadius: BorderRadius.circular(12),
      ),
      child: Column(
        children: [
          const Text(
            '计数器',
            style: TextStyle(
              fontSize: 14,
              color: Colors.white70,
            ),
          ),
          const SizedBox(height: 16),
          Text(
            '$_counter',
            style: const TextStyle(
              fontSize: 48,
              fontWeight: FontWeight.bold,
              color: Colors.white,
            ),
          ),
          const SizedBox(height: 16),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: _decrement,
                style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.green.withOpacity(0.3),
                  foregroundColor: Colors.white,
                ),
                child: const Icon(Icons.remove),
              ),
              const SizedBox(width: 16),
              ElevatedButton(
                onPressed: _increment,
                style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.green.withOpacity(0.3),
                  foregroundColor: Colors.white,
                ),
                child: const Icon(Icons.add),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

class LikeButtonWidget extends StatefulWidget {
  const LikeButtonWidget({super.key});

  @override
  State<LikeButtonWidget> createState() => _LikeButtonWidgetState();
}

class _LikeButtonWidgetState extends State<LikeButtonWidget> {
  bool _isLiked = false;
  int _likeCount = 128;

  void _toggleLike() {
    setState(() {
      _isLiked = !_isLiked;
      _likeCount += _isLiked ? 1 : -1;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.green.withOpacity(0.1),
        borderRadius: BorderRadius.circular(12),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          GestureDetector(
            onTap: _toggleLike,
            child: Container(
              padding: const EdgeInsets.all(12),
              decoration: BoxDecoration(
                color: _isLiked
                    ? Colors.red.withOpacity(0.3)
                    : Colors.white.withOpacity(0.1),
                shape: BoxShape.circle,
              ),
              child: Icon(
                _isLiked ? Icons.favorite : Icons.favorite_border,
                color: _isLiked ? Colors.red : Colors.white70,
                size: 24,
              ),
            ),
          ),
          const SizedBox(width: 16),
          Text(
            '$_likeCount',
            style: const TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.bold,
              color: Colors.white,
            ),
          ),
          const SizedBox(width: 8),
          Text(
            '人点赞',
            style: TextStyle(
              fontSize: 14,
              color: Colors.white.withOpacity(0.7),
            ),
          ),
        ],
      ),
    );
  }
}

// 生命周期示例
class LifecycleWidget extends StatefulWidget {
  const LifecycleWidget({super.key});

  @override
  State<LifecycleWidget> createState() => _LifecycleWidgetState();
}

class _LifecycleWidgetState extends State<LifecycleWidget> {
  final List<String> _logs = [];
  int _counter = 0;

  void _addLog(String log) {
    setState(() {
      _logs.insert(0, '$log (${DateTime.now().millisecondsSinceEpoch % 10000})');
      if (_logs.length > 5) _logs.removeLast();
    });
  }

  @override
  void initState() {
    super.initState();
    _addLog('initState');
  }

  @override
  void didUpdateWidget(LifecycleWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    _addLog('didUpdateWidget');
  }

  void _rebuild() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.purple.withOpacity(0.1),
        borderRadius: BorderRadius.circular(12),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              const Text(
                '生命周期日志',
                style: TextStyle(
                  fontSize: 14,
                  color: Colors.white70,
                ),
              ),
              ElevatedButton(
                onPressed: _rebuild,
                style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.purple.withOpacity(0.3),
                  foregroundColor: Colors.white,
                  padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
                ),
                child: const Text('重建'),
              ),
            ],
          ),
          const SizedBox(height: 12),
          ..._logs.map((log) => Padding(
                padding: const EdgeInsets.only(bottom: 4),
                child: Row(
                  children: [
                    Container(
                      width: 4,
                      height: 4,
                      margin: const EdgeInsets.only(right: 8),
                      decoration: const BoxDecoration(
                        color: Colors.purple,
                        shape: BoxShape.circle,
                      ),
                    ),
                    Expanded(
                      child: Text(
                        log,
                        style: TextStyle(
                          fontSize: 12,
                          color: Colors.white.withOpacity(0.9),
                          fontFamily: 'monospace',
                        ),
                      ),
                    ),
                  ],
                ),
              )),
        ],
      ),
    );
  }
}

// 性能优化示例
class PerformanceWidget extends StatefulWidget {
  const PerformanceWidget({super.key});

  @override
  State<PerformanceWidget> createState() => _PerformanceWidgetState();
}

class _PerformanceWidgetState extends State<PerformanceWidget> {
  int _clickCount = 0;
  int _buildCount = 0;

  @override
  Widget build(BuildContext context) {
    _buildCount++;
    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.orange.withOpacity(0.1),
        borderRadius: BorderRadius.circular(12),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const Text(
            '性能测试',
            style: TextStyle(
              fontSize: 14,
              color: Colors.white70,
            ),
          ),
          const SizedBox(height: 12),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              ElevatedButton(
                onPressed: () {
                  setState(() {
                    _clickCount++;
                  });
                },
                style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.orange.withOpacity(0.3),
                  foregroundColor: Colors.white,
                ),
                child: const Text('点击'),
              ),
              Text(
                '点击次数: $_clickCount',
                style: const TextStyle(
                  fontSize: 14,
                  color: Colors.white,
                ),
              ),
            ],
          ),
          const SizedBox(height: 12),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              const Text(
                '构建次数:',
                style: TextStyle(
                  fontSize: 14,
                  color: Colors.white70,
                ),
              ),
              Text(
                '$_buildCount',
                style: const TextStyle(
                  fontSize: 14,
                  fontWeight: FontWeight.bold,
                  color: Colors.white,
                ),
              ),
            ],
          ),
          const SizedBox(height: 12),
          Container(
            padding: const EdgeInsets.all(12),
            decoration: BoxDecoration(
              color: Colors.white.withOpacity(0.05),
              borderRadius: BorderRadius.circular(8),
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const Text(
                  '提示:',
                  style: TextStyle(
                    fontSize: 12,
                    fontWeight: FontWeight.bold,
                    color: Colors.orange,
                  ),
                ),
                const SizedBox(height: 4),
                Text(
                  '每次点击都会触发 setState,\n导致整个组件重建。\n优化思路:将频繁变化的部分\n分离为独立的 Stateful Widget。',
                  style: TextStyle(
                    fontSize: 11,
                    color: Colors.white.withOpacity(0.8),
                    height: 1.4,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

八、总结

StatelessWidget 和 StatefulWidget 是 Flutter 状态管理的基础,理解它们的区别和使用场景对于开发高效的应用至关重要。

🎯 核心要点

  • StatelessWidget:状态不可变,适用于纯展示组件,性能高效
  • StatefulWidget:状态可变,通过 State 对象管理状态,需要响应交互
  • 生命周期:StatefulWidget 有完整的生命周期,需要正确管理资源
  • setState:触发 UI 重建的关键方法,不能在 build 中调用
  • 性能优化:使用 const、RepaintBoundary 等技巧提升性能

📚 使用建议

场景 推荐方案
纯文本展示 StatelessWidget
数据展示卡片 StatelessWidget(数据由父组件传入)
按钮交互 StatefulWidget 或使用 GestureDetector
表单输入 StatefulWidget
动画效果 StatefulWidget + AnimationController
复杂状态管理 考虑使用状态管理库(Provider、Riverpod 等)

💡 最佳实践:优先使用 StatelessWidget,只有在确实需要管理状态时才使用 StatefulWidget。通过合理的状态管理,可以让代码更简洁、性能更优。随着应用复杂度的增加,可以考虑引入专门的状态管理方案。

相关推荐
微祎_10 小时前
Flutter for OpenHarmony:链迹 - 基于Flutter的会话级快速链接板极简实现方案
flutter
微祎_11 小时前
Flutter for OpenHarmony:魔方计时器开发实战 - 基于Flutter的专业番茄工作法应用实现与交互设计
flutter·交互
麟听科技15 小时前
HarmonyOS 6.0+ APP智能种植监测系统开发实战:农业传感器联动与AI种植指导落地
人工智能·分布式·学习·华为·harmonyos
前端不太难16 小时前
HarmonyOS PC 焦点系统重建
华为·状态模式·harmonyos
空白诗16 小时前
基础入门 Flutter for Harmony:Text 组件详解
javascript·flutter·harmonyos
lbb 小魔仙17 小时前
【HarmonyOS】React Native实战+Popover内容自适应
react native·华为·harmonyos
喝拿铁写前端17 小时前
接手老 Flutter 项目踩坑指南:从环境到调试的实际经验
前端·flutter
renke336417 小时前
Flutter for OpenHarmony:单词迷宫 - 基于路径探索与字母匹配的认知解谜系统
flutter
motosheep18 小时前
鸿蒙开发(四)播放 Lottie 动画实战(Canvas 渲染 + 资源加载踩坑总结)
华为·harmonyos
火柴就是我18 小时前
我们来尝试实现一个类似内阴影的效果
android·flutter