Определение виджетов внутри initState или конструкторов классов, а не сборка? - PullRequest
0 голосов
/ 17 октября 2018

Большинство примеров и преобладающей мудрости, которую я вижу, используют типичный шаблон для виджета в классе, где ВСЕ дополнительные виджеты создаются в методе build (который, я думаю, может дать ясность кода, но оставляя это в стороне).).

Однако, если указанный виджет больше не изменится, он все равно будет воссоздан при каждом вызове сборки.Есть ли какая-либо реальная проблема с присвоением этого в initState или конструкторе класса и ссылкой на него позже?

Тривиализированный пример

// this partial from inside the build() method currently
Container(
  padding: const EdgeInsets.only(bottom: 8.0),
    child: Text(
      'Oeschinen Lake Campground',
       style: TextStyle(
       fontWeight: FontWeight.bold,
    ),
  ),
 ),

на

// Now inside initState or class Constructor
myText = Text(
      'Oeschinen Lake Campground',
       style: TextStyle(
       fontWeight: FontWeight.bold,
    ),
 );

...
// Still inside build method (in fact this could also go inside the constructor ?)
Container( 
  padding: const EdgeInsets.only(bottom: 8.0),
  child: myText
)

Thisтолько для кода, который не основан на ссылке на состояние.

Есть ли какие-либо недостатки, кроме дизайна / эстетики, чтобы сделать это таким образом?Хотя этот пример тривиален, я продолжаю думать, что, возможно, есть некоторые преимущества в производительности / аккумуляторе / свободном пространстве, когда нет необходимости перестраивать не зависящие от состояния виджеты, когда приложение становится намного более сложным (я также знаю, что виджет дальшевверх дерево может по-прежнему вызывать новый объект каждый раз).Тем не менее, я новичок в изучении флаттера / дротика, поэтому настороженно отношусь к некоторым проблемам, которые я не учел должным образом, или по сути неправильно понял некоторые аспекты.

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

Это законная оптимизация.Фактически вы можете сделать то же самое с виджетами, зависящими от состояния (в сочетании с didUpdateWidget).Тем не менее, выигрыш незначителен.

Виджеты чрезвычайно легки, а Дарт оптимизирован для множества микроинстанций.

И с этим подходом есть одна проблема: вы теряете горячую перезагрузку.


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

Это очень часто используется в анимациях, чтобы не перестраивал все дерево виджетов каждые кадры.Типичным примером будет AnimatedBuilder (но все XXTransition следуют той же логике)

Animation animation;

AnimatedBuilder(
  animation: animation,
  child: Text('Foo'),
  builder: (context, child) {
    return Align(
      alignment: Alignment(.5, animation.value),
      child: child,
    );
  },
);

Здесь это добровольно повторно использует экземпляр child, так что метод сборки Text не вызываетсяснова.


Итак, я должен это делать или нет?

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

Чтобы повторно использовать ваш пример, вы можете извлечь свое "всегда одинаковое" дерево виджетов в пользовательский виджет с помощью конструктора const:

class _Foo extends StatelessWidget {
  const _Foo({Key key}): super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text(
      'Oeschinen Lake Campground',
      style: TextStyle(
        fontWeight: FontWeight.bold,
      ),
    );
  }
}

, а затем используйте его в своем методе build:

@override
Widget build(BuildContext context) {
  return Container(
    padding: const EdgeInsets.only(bottom: 8.0),
    child: const _Foo(),
  );
}

Таким образом вы получите преимущества кэширования экземпляра виджета.НО вы не теряете горячую перезагрузку.

Идеально верно?

0 голосов
/ 17 октября 2018

TL; DR : Не надо.


Сначала давайте посмотрим, что скажет по этому поводу инженер Гуглер и Флаттер Мэтт Салливан :

С Flutter, создающим и разрушающим объекты с большой частотой, разработчики должны предпринять шаги, чтобы ограничить это поведение?Нередко новые разработчики Flutter создают ссылки на виджеты, которые, как они знают, не изменятся со временем, и переводят их в состояние, чтобы они не были уничтожены и восстановлены.

Не делайте этого.

Чтобы понять, почему это плохая идея, вам прежде всего нужно понять, что Widget s делают очень мало .Поскольку они обычно просто составляют другие Widget s или создают RenderObject s, они не выполняют фактический рендеринг;все тяжелые работы выполняются RenderObject с.Вы можете думать о Widget s как о сверхлегких «чертежах» для RenderObject s.
Также обратите внимание, что RenderObject s сильно кэшируется самой платформой Flutter, поэтому, если вы создадите несколько подобных Widgetв последовательных сборках базовый RenderObject автоматически повторно используется . Кэшируя ваш пользовательский интерфейс, вы эффективно воссоздаете функциональность, которую конвейер рендеринга Flutter предоставляет из коробки .Только из-за этого многие люди будут утверждать, что дополнительная сложность вашего кода не стоит этого.

"Хорошо, тогда" Вы можете подумать, "Повышение производительности можетбыть очень очень маленьким, но он существует, верно? "

На самом деле, нет.Это связано с тем, что базовая среда выполнения Dart использует два типа сборщиков мусора: сборщик мусора Young Space Scavenger для недолговечных объектов и сборщик мусора mark-sweep для долгоживущих объектов.Для более подробного объяснения того, как они работают, ознакомьтесь с этой статьей с подходящим названием "Не бойтесь сборщика мусора".
По сути, это говорит о том, что Young Space Scavenger намного быстрее, чем коллектор mark-sweep , и если приложение не придерживается «гипотезы слабого поколения», которая гласит, что большинство объектов умирают молодыми, тогда mark-sweep ingбудет происходить чаще.Короче говоря, производительность может на самом деле ухудшиться .

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...