Действительно ли расширение виджета является антипаттерном?

Aug 20 2020

Я читал в паре мест, что расширение виджета Flutter - это антипаттерн. Это правда?

Я использовал подклассы виджетов, чтобы сократить вложенность, создав подкласс виджета, который я удаляю, и поместил его виджеты в его конструктор, например

class Foo extends FormBuilder {
    Foo() : super (
        // bunch of widgets here
    );
}

Расширение виджета без сохранения состояния кажется более популярным, но оно добавляет к дереву еще несколько строк кода и виджет, что мне не нравится:

class Foo extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return FormBuilder(
       // bunch of widgets here
    );
}

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

Ответы

3 kuhnroyal Aug 20 2020 at 20:22

Расширение виджетов с отслеживанием состояния может привести к проблемам, поскольку их состояние типизировано для суперкласса, и вы не можете расширить их состояние, поскольку большинство классов состояний остаются закрытыми. Многие методы поиска, такие как BuildContext.findAncestorStateOfType().

Расширение виджетов без состояния должно работать в большинстве случаев, но, как вы уже заметили, не рекомендуется.

В целом, при всей реактивной и виджетной природе Flutter принцип композиции над наследованием - хороший образец для подражания.

Вы составляете из виджетов новые виджеты, новые виджеты, новые виджеты, новые виджеты ... Вы уловили суть.

Кроме того, вы сохраняете 2 строки кода, которые в основном генерируются автоматически, но вы лишаете себя всех простых помощников в VSCode / IntelliJ, таких как «Обернуть виджет с заполнением». Намного сложнее обернуть расширенный FormBuilderотступ для всех случаев использования в вашем приложении. Если составить его несложно, просто заверните внутрь Foo. То же самое и со всеми другими виджетами, которые вы используете для оформления тем, цветов, стилей шрифтов и т. Д. - отступы являются лишь примером.

2 jitsm555 Aug 20 2020 at 21:16

Flutter - это скорее из composition, чем Inheritance. Но наследование с использованием StatelessWidget всегда будет полезно, когда родительские виджеты необходимо повторно использовать в дочерних.

Например:

class FormBuilder extends StatelessWidget {
  Widget getWidget() {
    return Text('Child Text');
  }

  @override
  Widget build(BuildContext context) {
    return Text('FormBuilder Text');
  }
}

class Foo extends FormBuilder {
  Foo() : super();

  @override
  Widget build(BuildContext context) {
    return getWidget();
  }
}

Итак, виджет, который вызовет виджет Foo () , дерево элементов виджета будет

- Фу

- контейнер

Если это нормальная композиция, тогда дерево элементов будет для этого

class Foo extends StatelessWidget {
      Foo() : super();
    
      @override
      Widget build(BuildContext context) {
        return FormBuilder();
      }
    }

- Фу

- FormBuilder

- текст

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