flutter 在小部件树中使用const是否可以提高性能?

l7mqbcuq  于 2023-03-03  发布在  Flutter
关注(0)|答案(4)|浏览(222)

创建小部件树时,在静态小部件之前插入const是否会提高性能?

child: const Text('This is some text');

对比

child: Text('This is some text');

我知道,在Dart 2中,const是可选的,并且会在某些地方自动插入。这是其中一种情况吗?如果不是,使用const是否会减少内存使用/提高性能?

oknrviil

oknrviil1#

这是一个很小的性能改进,但它可以在较大的应用程序或视图经常重建的应用程序中(例如,由于动画)累积起来。
const减少了垃圾收集器所需的工作。
您可以在analysis_options.yaml中启用一些linter规则,这些规则告诉您应该何时添加const,因为它不是推断的,而是可能的,例如

或者在使用const时提醒您,但无论如何都是推断的

另请参见https://www.dartlang.org/guides/language/analysis-options

idv4meu8

idv4meu82#

在Flutter的例子中,const的真正好处是"不"具有更少的示例化。Flutter对小部件的示例不改变有一个特殊的处理:它不能重建它们。
请考虑以下几点:

Foo(
  child: const Bar(
    child: Baz() 
  ),
)

build方法被再次调用的情况下(setState、父重建、Inheritedwidget ...),则由于Bar子树的const,只有Foo将看到其build方法被调用。
Bar将 * 永远 * 不会因为其父对象而被重新构建,因为Flutter知道,既然小部件示例没有更改,就没有什么要更新的。

kpbwa7wx

kpbwa7wx3#

**更新:**我注意到最近我收到了一个赞成票,我必须说我对下面的测试没有信心,但这就是我得到的全部。所以最好有人运行一个更好的测试。

我做了些测试看看有没有影响。
这些测试主要基于在this article中完成的测试。
在测试中,有300个容器,里面的文本在屏幕上随机移动,这是你在日常应用程序中看不到的。
对于我的结果来说,每秒帧数没有差别,内存使用也没有差别,除了垃圾收集器在不使用常量时似乎运行得更频繁。

我的意思是,性能提升是微不足道的,听起来像是抢先优化。然而,在测试中没有嵌套的小部件链,但我不认为这会有什么不同。上面的文章似乎说有一个小的,但这不是我的测试显示。
我有一张这样的卡片(这是const版本):

import 'package:flutter/material.dart';

class MyCard extends StatelessWidget {
  const MyCard();

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Container(
        margin: const EdgeInsets.all(8.0),
        height: 100,
        width: 100,
        color: Colors.red,
        child: const Text('Hi'),
      ),
    );
  }
}

它被渲染了300次,并在屏幕上随机移动。
这是一个让它们移动的小工具

import 'package:flutter/material.dart';
import 'dart:math';
import 'dart:async';
import './my-card.dart';

class MovingContainer extends StatefulWidget {
  @override
  _MovingContainerState createState() => _MovingContainerState();
}

class _MovingContainerState extends State<MovingContainer> {
  final Random _random = Random();
  final Duration _duration = const Duration(milliseconds: 1000);
  Timer _timer;
  double _top = 0;
  double _left = 0;

  @override
  void initState() {
    super.initState();
    initMove();
  }

  void initMove() {
    _timer = Timer.periodic(
      _duration,
      (timer) {
        move();
      },
    );
  }
  void move() {
    final Size size = MediaQuery.of(context).size;
    setState(() {
      _top = _random.nextInt(size.height.toInt() - 100).toDouble();
      _left = _random.nextInt(size.width.toInt() - 100).toDouble();
    });
  }

  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedPositioned(
      top: _top,
      left: _left,
      child: const MyCard(),
      duration: _duration,
    );
  }
}

注意:我是flutter的新手,其他人也是,因为它是一个相对较新的框架。因此,我的测试很可能是错误的,不要把它当作福音。当你读到一篇名为《头号性能增益在Flutter上》的文章时,也不要把它当作福音。我还没有看到实际的证据证明有性能增益。

m1m5dgzv

m1m5dgzv4#

当我们使用setState()时,Flutter调用build方法并重建其中的每个小部件树,避免这种情况的最好方法是使用const构造函数。
在构建自己的小部件或使用Flutter小部件时,尽可能使用const构造函数。这有助于Flutter只重新构建应该更新的小部件。
因此,如果您有一个StatefulWidget,并且使用setState((){})更新该小部件,那么您有如下小部件:

class _MyWidgetState extends State<MyWidget> {

  String title = "Title";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Column(
        children: <Widget>[
          const Text("Text 1"),
          const Padding(
            padding: const EdgeInsets.all(8.0),
            child: const Text("Another Text widget"),
          ),
          const Text("Text 3"),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.add),
        onPressed: () {
          setState(() => title = 'New Title');
        },
      ),
    );
  }
}

相关问题