Flutter - StatelessWidget和StatefulWidget

133 阅读1分钟

对比 Flutter Widget 和 Jetpack Compose 来解释:

1. StatelessWidget - 类似 Compose 中的无状态组件

// Flutter - StatelessWidget
class GreetingCard extends StatelessWidget {
  final String name;
  
  const GreetingCard({required this.name});
  
  @override
  Widget build(BuildContext context) {
    return Card(
      child: Text('Hello, $name!'),
    );
  }
}

// Compose 对应写法
@Composable
fun GreetingCard(name: String) {
    Card {
        Text("Hello, $name!")
    }
}

特点:

  • 像纯函数一样,输入相同则输出相同
  • 不保存状态
  • 适合展示静态内容

2. StatefulWidget - 类似 Compose 中使用 remember 的组件

// Flutter - StatefulWidget
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(() {
              count++;
            });
          },
          child: Text('Increment'),
        ),
      ],
    );
  }
}

// Compose 对应写法
@Composable
fun Counter() {
    var count by remember { mutableStateOf(0) }
    
    Column {
        Text("Count: $count")
        Button(onClick = { count++ }) {
            Text("Increment")
        }
    }
}

特点:

  • 可以保存和更新状态
  • 状态改变时会重建 UI
  • 适合交互性组件

3. 实际应用场景

// Flutter - 购物车商品项
class CartItem extends StatelessWidget {
  final String name;
  final double price;
  final String image;
  
  const CartItem({
    required this.name,
    required this.price,
    required this.image,
  });
  
  @override
  Widget build(BuildContext context) {
    return ListTile(
      leading: Image.network(image),
      title: Text(name),
      subtitle: Text('\$$price'),
    );
  }
}

// Compose 对应写法
@Composable
fun CartItem(
    name: String,
    price: Double,
    image: String
) {
    ListItem(
        leadingContent = {
            AsyncImage(model = image)
        },
        headlineText = { Text(name) },
        supportingText = { Text("$${price}") }
    )
}

4. 带状态的实际例子

// Flutter - 可编辑的个人资料
class EditProfile extends StatefulWidget {
  @override
  _EditProfileState createState() => _EditProfileState();
}

class _EditProfileState extends State<EditProfile> {
  String name = '';
  String bio = '';
  
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextField(
          onChanged: (value) {
            setState(() {
              name = value;
            });
          },
          decoration: InputDecoration(
            labelText: 'Name',
          ),
        ),
        TextField(
          onChanged: (value) {
            setState(() {
              bio = value;
            });
          },
          decoration: InputDecoration(
            labelText: 'Bio',
          ),
        ),
        ElevatedButton(
          onPressed: () {
            // 保存资料
          },
          child: Text('Save'),
        ),
      ],
    );
  }
}

// Compose 对应写法
@Composable
fun EditProfile() {
    var name by remember { mutableStateOf("") }
    var bio by remember { mutableStateOf("") }
    
    Column {
        OutlinedTextField(
            value = name,
            onValueChange = { name = it },
            label = { Text("Name") }
        )
        
        OutlinedTextField(
            value = bio,
            onValueChange = { bio = it },
            label = { Text("Bio") }
        )
        
        Button(onClick = { /* 保存资料 */ }) {
            Text("Save")
        }
    }
}

5. 生命周期对比

// Flutter - StatefulWidget 生命周期
class LifecycleWidget extends StatefulWidget {
  @override
  _LifecycleWidgetState createState() => _LifecycleWidgetState();
}

class _LifecycleWidgetState extends State<LifecycleWidget> {
  @override
  void initState() {
    super.initState();
    // 初始化,类似 Compose 的 SideEffect
  }
  
  @override
  void dispose() {
    // 清理,类似 Compose 的 DisposableEffect
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

// Compose 对应写法
@Composable
fun LifecycleDemo() {
    DisposableEffect(Unit) {
        // 初始化
        onDispose {
            // 清理
        }
    }
}

总结:

  1. StatelessWidget vs 无状态 Composable

    • 都是纯展示组件
    • 依赖外部传入的数据
    • 不维护内部状态
  2. StatefulWidget vs 有状态 Composable

    • 都可以维护内部状态
    • Flutter 使用 setState
    • Compose 使用 remember 和 mutableStateOf
  3. 主要区别

    • Flutter 分离状态和 UI(State 类)
    • Compose 状态和 UI 在一起
    • Flutter 更面向对象
    • Compose 更函数式
  4. 使用建议

    • 优先使用 StatelessWidget/无状态组件
    • 需要状态时才用 StatefulWidget/状态组件
    • 合理拆分组件
    • 状态下沉,UI 上浮
  5. 性能考虑

    • StatelessWidget 更轻量
    • 状态改变范围要合理
    • 避免不必要的重建
    • 适当使用缓存