Menu
CoddyTech

提升状态

本课属于 Coddy Flutter 学习旅程的“状态管理”单元。第 4 课,共 27 课。

轻点手机上的拇指图标:旁边的数字会增加,但顶部栏仍显示 0 likes。按钮会把计数保存在自己的 State 中,其他地方都无法访问它。

当两个组件需要使用同一个值时,把它移到同时包含这两个组件的最近一个组件中。这称为状态提升。页面持有 likes,按钮则变成一个 StatelessWidget,接收这个值和一个回调函数:

LikeButton(
  likes: likes,
  onLike: () {
    setState(() {
      likes++;
    });
  },
)

现在,计数只保存在一个地方。顶部栏、按钮和重置按钮都会读取并修改这个值,因此它们永远不会出现不一致。

快速测试:如果一个值在两个地方显示或改变,那么持有它的组件必须位于这两个组件的上方。

challenge icon

挑战

中等

让页面成为 likes 的唯一所有者:

  • 将 LikeButton 改为一个 StatelessWidget,并包含两个字段:likes 和 onLike 回调。
  • 页面传入自己的 likes,并传入一个在 setState 中将其加 1 的 onLike。

这样,顶部栏就会跟随按钮变化,刷新按钮会将两者都重置。

亲手试试

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    );
  }
}

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int likes = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('$likes likes'),
        actions: [
          IconButton(
            icon: const Icon(Icons.refresh),
            onPressed: () {
              setState(() {
                likes = 0;
              });
            },
          ),
        ],
      ),
      body: const Center(
        child: LikeButton(),
      ),
    );
  }
}

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

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

class _LikeButtonState extends State<LikeButton> {
  int likes = 0;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        IconButton(
          icon: const Icon(Icons.thumb_up),
          iconSize: 40,
          onPressed: () {
            setState(() {
              likes++;
            });
          },
        ),
        Text('$likes', style: const TextStyle(fontSize: 32)),
      ],
    );
  }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

状态管理中的所有课

自己练习: Flutter 在线编译器