StatelessWidget против функции, возвращающей виджеты с точки зрения производительности - PullRequest
0 голосов
/ 22 февраля 2019

Есть ли разница в производительности при использовании StatelessWidget против function returning a Widget?

Мне хорошо известны, по крайней мере, различия, отмеченные в этом репо-выпуске флаттера , которые не связаны с производительностью.

Дело в том, что япусть некоторые коллеги утверждают, что functional widgets худшие с точки зрения производительности, но после прочтения немного об этом предмете я не могу найти какой-либо убедительной части документации, которая могла бы подтвердить это утверждение, поэтому любые разъяснения по этому вопросу будут очень приветствоваться!

Насколько я вижу, единственное различие между ними будет в случае использования const Widget, что, по-видимому, позволит избежать фазы восстановления.

1 Ответ

0 голосов
/ 22 февраля 2019

Прежде всего, я хотел бы отметить, что пакет доступен для создания StatelessWidget из функции: functions_widget


Прирост производительности не являетсяобязательно верно.Это зависит от того, как вы используете свои виджеты, в основном от того, как вы используете их для управления своим состоянием.

По умолчанию классы могут ухудшать производительность, в отличие от функций в приложении, которое не использует их мощность.

Реальный вопрос: в чем их сила?

Простой: классы могут обновляться независимо друг от друга.Функции не могут

Классы могут частично обновлять дерево виджетов.

Рассмотрим виджет, который перестраивает каждый кадр и возвращает его дочерний элемент:

class InfiniteLoop extends StatefulWidget {
  const InfiniteLoop({Key key, this.child}) : super(key: key);
  final Widget child;
  @override
  _InfiniteLoopState createState() => _InfiniteLoopState();
}

class _InfiniteLoopState extends State<InfiniteLoop> {
  @override
  Widget build(BuildContext context) {
    WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {}));

    return widget.child;
  }
}

Теперь, если мы поместим все наше приложение в этот виджет, что произойдет?

void main() => runApp(InfiniteLoop(child: MyApp()));

Ничего

Конечно, у вас будет один виджет, который часто перестраиваетсяв вашем дереве.Но на самом деле build метод MyApp будет вызываться только один раз.

Это потому, что Flutter может прервать восстановление дерева, когда экземпляр виджета не изменится.


Классы могут злоупотреблять этой оптимизацией.

Используя классы, можно хитро разделить восстановление вашего дерева виджетов на независимые части.

Нет смысла перечислять все потенциальные факторы оптимизации, которые допускает класс, поскольку их слишком много.

В следующем примере представлен виджет, который принимает int и форматирует его в Text.Уловка в том, что этот виджет будет перестраивать только , если int прошло изменение:

class Counter extends StatelessWidget {
  const Counter({Key key, this.value}) : super(key: key);

  final int value;

  @override
  Widget build(BuildContext context) {
    return Text(value.toString());
  }

  @override
  bool operator ==(Object other) =>
      identical(this, other) || (other is Counter && other.value == value);

  @override
  int get hashCode => value.hashCode;
}

Это работает, потому что Flutter использует оператор ==, чтобы знать, должен ли виджет обновляться илинет (следовательно, почему конструктор const является хорошим фактором оптимизации).

Это не единственное решение, но хороший пример того, что функции не могут сделать.

...