Flutter - SetState 不适用于提取的小部件

Flutter - SetState not working on extracted widgets

你好,基本上我想知道为什么 setState() 适用于提取为方法的小部件,但不适用于提取为小部件的小部件....

以及何时使用提取的小部件/提取的小部件作为方法,或者它们是否相同?但我想它们不可能是一样的,因为一个有效而另一个无效?

如果您想要我在将其更改为提取方法之前尝试过的代码:

来自主要 class:

void refresh() => setState(() {});

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        resizeToAvoidBottomInset: false,
        backgroundColor: Colors.blue,
        body: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: const [
            SizedBox(height: 50),
            PageHeader(),
            PageBody(),
          ],
        ),
        floatingActionButton: AddTaskButton(
          transitionAnimationController: transitionAnimationController,
          refresh: refresh,
        ),
      ),
    );
  }

提取的小部件:

class PageHeader extends StatelessWidget {
  const PageHeader({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Expanded(
      flex: 1,
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 15.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const CircleAvatar(
              radius: 30,
              backgroundColor: Colors.white,
              child: Icon(
                Icons.list,
                color: Colors.blue,
                size: 30,
              ),
            ),
            const SizedBox(
              height: 15,
            ),
            const Text(
              'Todoey',
              style: TextStyle(color: Colors.white, fontSize: 35),
            ),
            Text(
              ' ${TaskData.tasks.length} Tasks',
              style: const TextStyle(color: Colors.white, fontSize: 15),
            ),
          ],
        ),
      ),
    );
  }
}

class PageBody extends StatelessWidget {
  const PageBody({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Expanded(
      flex: 3,
      child: Container(
        decoration: const BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.only(
            topLeft: Radius.circular(20),
            topRight: Radius.circular(20),
          ),
        ),
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 15.0),
          child: TaskList(taskData: TaskData.tasks),
        ),
      ),
    );
  }
}

提取的方法:

Expanded pageHeader() {
    return Expanded(
      flex: 1,
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 15.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const CircleAvatar(
              radius: 30,
              backgroundColor: Colors.white,
              child: Icon(
                Icons.list,
                color: Colors.blue,
                size: 30,
              ),
            ),
            const SizedBox(
              height: 15,
            ),
            const Text(
              'Todoey',
              style: TextStyle(color: Colors.white, fontSize: 35),
            ),
            Text(
              ' ${TaskData.tasks.length} Tasks',
              style: const TextStyle(color: Colors.white, fontSize: 15),
            ),
          ],
        ),
      ),
    );
  }
}

Expanded pageBody() {
  return Expanded(
    flex: 3,
    child: Container(
      decoration: const BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(20),
          topRight: Radius.circular(20),
        ),
      ),
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 15.0),
        child: TaskList(taskData: TaskData.tasks),
      ),
    ),
  );
}

您提取的小部件是无状态 小部件。

setState() 仅适用于 有状态 小部件。

为了获得更好的性能,使用提取的小部件比使用提取的方法更好。

setState()其实并不关心是不是提取widget的och方法。它没有对此进行“检查”。

它告诉 UI 小部件的状态已更改,可能需要重绘。它安排了一个新的构建。但如果它没有 to.

,它不一定会重绘所有内容

因此,根据 parent 小部件(调用 setState)下方的小部件类型及其包含的内容,它们可能会被重绘。

但是,重绘时总是调用一个方法(“通过方法提取小部件”),非常un-efficient。这就是为什么您可能会观察到差异。

观看此视频以了解有关差异的更多信息:

https://www.youtube.com/watch?v=IOyq-eTRhvo

根据经验,“始终”提取小部件,而不是通过方法创建小部件。

为什么您的 child 小部件没有重建可能是多种原因之一。无论哪种方式,我认为它与本例中的 parents setState() 调用没有任何关系。

child 小部件没有任何理由重建。您似乎正在通过一些全局变量(?)TaskData.tasks...添加内容? child 小部件不会“观察”该变量的变化。所以他们没有重建的理由。

如果您从 parent 注入数据,使用一些状态管理,如 Bloc,或使用 Provider 或 ChangeNotifier 或类似的,用于 PageHeader()、PageBody() 及其 children 建立他们的基础,然后一切都会相应地更新。