Я понял, что можно создавать виджеты с использованием простых функций вместо создания подкласса StatelessWidget . Примером может быть такой:
Widget function({ String title, VoidCallback callback }) {
return GestureDetector(
onTap: callback,
child: // some widget
);
}
Это интересно, потому что для этого требуется гораздо меньше кода, чем для полноценного класса. Пример:
class SomeWidget extends StatelessWidget {
final VoidCallback callback;
final String title;
const SomeWidget({Key key, this.callback, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: callback,
child: // some widget
);
}
}
Поэтому мне было интересно: есть ли какая-нибудь разница, помимо синтаксиса, между функциями и классами для создания виджетов? И полезно ли использовать функции?
Ответы:
TL; DR: предпочитайте использовать классы вместо функций для создания многоразового дерева виджетов.
РЕДАКТИРОВАТЬ : Чтобы исправить некоторое недоразумение: речь идет не о функциях, вызывающих проблемы, а о классах, решающих некоторые.
У Flutter не было бы StatelessWidget, если бы функция могла делать то же самое.
Точно так же он в основном предназначен для общедоступных виджетов, предназначенных для повторного использования. Не имеет большого значения, что частные функции предназначены для использования только один раз - хотя знать об этом поведении все равно хорошо.
Существует важное различие между использованием функций вместо классов, а именно: фреймворк не знает о функциях, но может видеть классы.
Рассмотрим следующую функцию «виджета»:
использовал этот способ:
И это эквивалент класса:
используется так:
На бумаге кажется, что оба делают одно и то же: создайте 2
Container
, причем одно вложено в другое. Но на самом деле все обстоит иначе.В случае функций сгенерированное дерево виджетов выглядит так:
Дерево виджетов с классами выглядит следующим образом:
Это важно, потому что это меняет поведение фреймворка при обновлении виджета.
Почему это важно
Используя функции для разделения дерева виджетов на несколько виджетов, вы подвергаетесь ошибкам и пропускаете некоторые оптимизации производительности.
Нет гарантии, что у вас будут ошибки при использовании функций, но при использовании классов вы гарантированно не столкнетесь с этими проблемами.
Вот несколько интерактивных примеров на Dartpad, которые вы можете запустить самостоятельно, чтобы лучше понять проблемы:
https://dartpad.dev/1870e726d7e04699bc8f9d78ba71da35
Этот пример демонстрирует, как, разделив приложение на функции, вы можете случайно сломать такие вещи, как
AnimatedSwitcher
https://dartpad.dev/a869b21a2ebd2466b876a5997c9cf3f1 В
этом примере показано, как классы позволяют более детально перестраивать дерево виджетов, повышая производительность.
https://dartpad.dev/06842ae9e4b82fad917acb88da108eee
Этот пример демонстрирует, как, используя функции, вы подвергаете себя злоупотреблению BuildContext и сталкиваетесь с ошибками при использовании InheritedWidgets (например, Theme или провайдеров).
Вывод
Вот тщательно подобранный список различий между использованием функций и классов:
showDialogs
и т.п.)ClassWidget
в дереве виджетов, которое показывает инструмент разработчика, что помогает понять, что находится на экране.Если происходит исключение (например, ProviderNotFound), фреймворк выдаст вам имя создаваемого в данный момент виджета. Если вы разделили дерево виджетов только на functions +
Builder
, у ваших ошибок не будет удобного названия.В целом, по этим причинам использование функций вместо классов для повторного использования виджетов считается плохой практикой.
Вы можете , но она может укусить вас в будущем.
источник
Я занимаюсь этим вопросом последние 2 дня. Я пришел к следующему выводу: НУЖНО разбивать части приложения на функции. Просто идеально, чтобы эти функции возвращали a
StatelessWidget
, чтобы можно было сделать оптимизацию, например, сделатьStatelessWidget
const
, чтобы он не перестраивался, если в этом нет необходимости. Например, этот фрагмент кода совершенно верен:Использование функции здесь совершенно нормально, поскольку она возвращает
const StatelessWidget
. Пожалуйста, поправьте меня, если я ошибаюсь.источник
const
перед классом без сохранения состояния в каждом случае? Или это должны быть определенные случаи? Если да, то какие?const
везде. Например, если у вас естьStatelessWidget
класс, который возвращает,Text
содержащий значение переменной, и эта переменная где-то изменяется, тогда вашStatelessWidget
должен быть перестроен, чтобы он мог отображать это другое значение, поэтому это не может бытьconst
. Я думаю, что безопасный способ сформулировать это так: где можно, используйтеconst
, если это безопасно.Была большая разница между тем, что делают функции и что делает класс.
Позвольте мне объяснить это с нуля. (Только про императив)
Все мы знаем, что история программирования началась с простых базовых команд (например, «Сборка»).
Далее Структурированное программирование пришло с элементами управления потоком (например: if, switch, while, for и т. Д.). Эта парадигма дает программистам возможность эффективно управлять потоком программы, а также минимизировать количество строк кода за циклами.
Далее пришло процедурное программирование, которое группирует инструкции в процедуры (функции). Это дало программистам два основных преимущества.
1. Сгруппируйте операторы (операции) в отдельные блоки.
2.Можно повторно использовать эти блоки. (Функции)
Но прежде всего парадигмы не дали решения для Управления приложениями. Процедурное программирование также можно использовать только для небольших приложений. Это нельзя использовать для разработки больших веб-приложений (например: банковское дело, google, youtube, facebook, stackoverflow и т. Д.), Нельзя создавать фреймворки, такие как android sdk, flutter sdk и многое другое ...
Поэтому инженеры проводят гораздо больше исследований, чтобы правильно управлять программами.
Наконец, объектно-ориентированное программирование поставляется со всеми решениями для управления приложениями любого масштаба (от привет, мир до триллиона людей, использующих создание системы, например, google, amazon, и сегодня 90% приложений).
В общем, все приложения построены на объектах. Это означает, что приложение представляет собой набор этих объектов.
Таким образом, объекты - это основа любого приложения.
класс (объект во время выполнения) группирует данные и функции, связанные с этими переменными (данными). поэтому объект состоит из данных и связанных с ними операций.
[Здесь я не буду объяснять о уп]
«Хорошо, теперь перейдем к фреймворку флаттера».
-Dart поддерживает как процедурные, так и oop. Но фреймворк Flutter полностью построен с использованием классов (oop). (Потому что большая управляемая структура не может быть создана с использованием процедурных)
Здесь я создам список причин, по которым они используют классы вместо функций для создания виджетов.
1 - Чаще всего метод сборки (дочерний виджет) вызывает ряд синхронных и асинхронных функций.
Пример:
поэтому метод сборки необходимо хранить в отдельном виджете класса (потому что все другие методы, вызываемые методом build (), могут храниться в одном классе)
2 - Используя класс виджета, вы можете создать номер другого класса, не записывая один и тот же код снова и снова (** Use Of Inheritance ** (extends)).
А также используя наследование (расширение) и полиморфизм (переопределение), вы можете создать собственный собственный класс. (Пример ниже: там я настрою (переопределю) анимацию, расширив MaterialPageRoute (потому что его переход по умолчанию, который я хочу настроить).
3 - Функции не могут добавлять условия для своих параметров, но с помощью конструктора виджета класса Вы можете это сделать.
Ниже пример кода👇 (эта функция активно используется виджетами фреймворка)
4 - Функции не могут использовать константу, а виджет класса может использовать константу для своих конструкторов. (которые влияют на производительность основного потока)
5 - Вы можете создать любое количество независимых виджетов, используя один и тот же класс (экземпляры класса / объектов). Но функция не может создавать независимые виджеты (экземпляр), а повторное использование может.
[у каждого экземпляра есть своя собственная переменная экземпляра, которая полностью независима от других виджетов (объекта), но локальная переменная функции зависит от каждого вызова функции * (что означает, что когда вы меняете значение локальной переменной, это влияет на все другие части приложение, которое использует эту функцию)]
У класса было много преимуществ над функциями ... (выше приведены только несколько вариантов использования)
🤯 Моя последняя мысль
Поэтому не используйте функции как строительный блок вашего приложения, используйте их только для выполнения операций. В противном случае это вызовет множество неуправляемых проблем, когда ваше приложение станет масштабируемым .
📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍 📍📍📍📍📍📍📍
ВЫ НЕ МОЖЕТЕ ИЗМЕРЯТЬ КАЧЕСТВО ПРОГРАММЫ ПО КОЛИЧЕСТВУ ЗАЯВЛЕНИЙ (или строк), ИСПОЛЬЗУЕМЫХ ею
📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍 📍📍📍📍📍📍📍
Спасибо за прочтение
источник
shrinkHelper() { return const SizedBox.shrink(); }
это то же самое, что использованиеconst SizedBox.shrink()
встроенного в дереве виджетов, а с помощью вспомогательных функций вы можете ограничить количество вложений в одном месте.Когда вы вызываете виджет Flutter, убедитесь, что вы используете ключевое слово const. Например
const MyListWidget();
источник
const
ключевого слова при вызове рефакторинга виджета без сохранения состояния его следует вызывать только один раз.