12 лучших практик для упрощения разработки приложений на Flutter в 2022 году

Flutter — один из самых популярных кроссплатформенных мобильных фреймворков от Google. Разработчики широко используют этот фреймворк по всему миру, поэтому существует шлейф обновленных версий Flutter, и последняя из них — Flutter 3.0.5. Сегодня мы поговорим о том, каковы лучшие практики разработки приложений на Flutter. Обращение к этому блогу упростит вам процесс разработки приложения на Flutter.

Лучшие практики для разработки приложений на Flutter
Здесь вы узнаете о лучших практиках для разработчиков Flutter для улучшения качества кода, читабельности, сопровождаемости и производительности. Давайте приступим:

  1. Сделайте функцию сборки чистойМетод сборки разрабатывается таким образом, что он должен быть чистым/без каких-либо ненужных вещей. Это связано с тем, что существуют определенные внешние факторы, которые могут вызвать сборку нового виджета, ниже приведены некоторые примеры:

Всплытие/нажатие маршрута
Изменение размера экрана, обычно из-за изменения вида или ориентации клавиатуры
Родительский виджет воссоздал своего ребенка
Наследуемый виджет, от которого зависит виджет (шаблон Class. of(context)), изменяется.
Избегайте:

@override
Widget build(BuildContext context context) {
return FutureBuilder(
future: httpCall(),
builder: (context, snapshot) {
// создаем здесь макет
},
);
}
Должно получиться вот так:

class Example extends StatefulWidget {
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State {
Future future;

@override
void initState() {
future = repository.httpCall();
super.initState();
}

@override
Widget build(BuildContext context) {
return FutureBuilder(
future: future,
builder: (context, snapshot) {
// создаем здесь макет
},
);
}
}

  1. Понимание концепции ограничений во FlutterСуществует правило макета Flutter, которое должен знать каждый разработчик приложений Flutter: ограничения идут вниз, размеры — вверх, а родитель задает позицию. Давайте разберемся в этом подробнее:

Виджет имеет свои собственные ограничения от своего родителя. Известно, что ограничение — это набор из четырех парных значений: минимальная и максимальная ширина, а также минимальная и максимальная высота.

Далее виджет проходит через свой собственный список дочерних элементов. Один за другим, виджет указывает своим детям их ограничения (которые могут быть разными для каждого ребенка), а затем спрашивает каждого ребенка, какого размера он хочет быть.

Затем виджет позиционирует своих детей (горизонтально по оси x и вертикально по оси y) одного за другим. А затем виджет уведомляет своего родителя о своем собственном размере (конечно, в рамках исходных ограничений).

Во Flutter все виджеты задают себя на основе ограничений своего родителя или своего бокса. Но это связано с некоторыми ограничениями.

Например, если у вас есть дочерний виджет внутри родительского виджета, и вы хотите определить его размер. Виджет не может иметь какой-либо размер сам по себе. Размер виджета должен быть в пределах ограничений, установленных его родителем.

  1. Умное использование операторов для сокращения количества строк для выполненияИспользование оператора CascadesЕсли мы должны выполнить последовательность операций над одним и тем же объектом, то нам следует выбрать оператор Cascades(…).

//Do
var path = Path()
..lineTo(0, size.height)
..lineTo(size.width, size.height)
..lineTo(size.width, 0)
..close();

//Не делать
var path = Path();
path.lineTo(0, size.height);
path.lineTo(size.width, size.height);
path.lineTo(size.width, 0);
path.close();
Использование коллекций спредов
Вы можете использовать разнесенные коллекции, когда существующие элементы уже хранятся в другой коллекции, синтаксис разнесенных коллекций приводит к более простому и легкому коду.

//Do
var y = [4,5,6];
var x = [1,2,…y];

//Не делать
var y = [4,5,6];
var x = [1,2];
x.addAll(y);
Используйте операторы Null safe (??) и Null aware (?.).
Всегда используйте операторы ?? (если null) и ?. (с учетом null) вместо проверки на null в условных выражениях.

//Do

v = a ?? b;
//Не
v = a == null ? b : a;

//Do
v = a ?b;
//Не делать
v = a == null ? null : a.b;
Избегайте использования оператора «as», вместо него используйте оператор «is»
Как правило, оператор as cast выбрасывает исключение, если приведение невозможно. Чтобы предотвратить исключение, можно использовать is.

//Do
if (item is Animal)
item.name = ‘Lion’;

//Do not
(item as Animal).name = ‘Lion’;

  1. Используйте потоки только при необходимостиХотя потоки довольно мощные, если мы используем их, то на наши плечи ложится большая ответственность за эффективное использование этого ресурса.

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

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

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

Вам нужно вызвать Sink.close(), чтобы остановить связанный StreamController, чтобы убедиться, что ресурсы могут быть позже освобождены GC.

Для этого нужно использовать метод StatefulWidget.dispose of:

abstract class MyBloc {
Sink foo;
Sink bar;
}

class MyWiget extends StatefulWidget {
@override
_MyWigetState createState() => _MyWigetState();
}

class _MyWigetState extends State {
MyBloc bloc;

@override
void dispose() {
bloc.bar.close();
bloc.foo.close();
super.dispose();
}

@override
Widget build(BuildContext context) {
// …
}
}

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

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

Юнит-тесты и виджет-тесты — это самые лучшие варианты, которые следует использовать с самого начала, и это совсем не так утомительно по сравнению с интеграционными тестами.

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

//Do
var s = ‘Это демонстрационная строка и $’;

//Не использовать
var s = ‘Это демонстрационная строка и $’;

  1. Используйте относительный импорт вместо абсолютного импортаПри совместном использовании относительного и абсолютного импорта возможна путаница, когда один и тот же класс импортируется двумя разными способами. Чтобы избежать этого, мы должны использовать относительный путь в папке lib/.

//Do
import ‘../../themes/style.dart’;

//Не
импортировать ‘package:myapp/themes/style.dart’;

  1. Использование SizedBox вместо Container в FlutterВо многих случаях вам потребуется использовать заполнитель. Ниже приведен идеальный пример:

return _isNotLoaded ? Container() : YourAppropriateWidget();
Контейнер — это отличный виджет, который вы будете активно использовать во Flutter. Container() расширяется, чтобы соответствовать ограничениям, заданным родителем, и не является const-конструктором.

Напротив, SizedBox является const-конструктором и создает поле фиксированного размера. Параметры width и height могут быть нулевыми, чтобы указать, что размер коробки не должен быть ограничен в соответствующем измерении.

Таким образом, когда нам нужно реализовать заполнитель, следует использовать SizedBox, а не контейнер.

return _isNotLoaded ? SizedBox() : YourAppropriateWidget();

  1. Используйте log вместо printprint() и debugPrint(), оба они всегда применяются для записи логов в консоль. Если вы используете print() и получаете слишком много вывода сразу, то Android иногда отбрасывает некоторые строки журнала.

Чтобы больше не сталкиваться с этим, используйте debugPrint(). Если данных журнала более чем достаточно, используйте dart: developer log(). Это позволит вам добавить немного больше детализации и информации в вывод журнала.

//Do
log(‘data: $data’);

//Не делать
print(‘data: $data’);
Используйте троичный оператор для однострочных случаев.
String alert = isReturningCustomer ? ‘Добро пожаловать на наш сайт!’ : ‘Добро пожаловать, пожалуйста, зарегистрируйтесь’;
Используйте условие if вместо троичного оператора для случая, как показано ниже.
Widget getText(BuildContext context) {
return Row(
children:
[
Text(«Hello»),
if (Platform.isAndroid) Text(«Android») (здесь, если вы используете троичную систему, то это неправильно)
]
);
}
Всегда старайтесь использовать виджеты const. Виджет не будет меняться при вызове setState, мы должны определить его как константу. Это будет препятствовать перестройке виджета, что приведет к снижению производительности.
//Do
const SizedBox(height: Dimens.space_normal)

//Do not
SizedBox(height: Dimens.space_normal)

  1. Не инициализируйте явно переменные nullВ Dart переменная интуитивно инициализируется в null, когда ее значение не указано, поэтому добавление null избыточно и необязательно.

//Do
int _item;

//Не делать
int _item = null;
Всегда выделяйте тип члена, если известен тип его значения. Не используйте var, когда это не требуется. Поскольку var является динамическим типом, для его разрешения требуется больше места и времени.
//Do
int item = 10;
final Car bar = Car();
String name = ‘john’;
const int timeOut = 20;

//Делать не
var item = 10;
final car = Car();
const timeOut = 2000;

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

Объявления Const также более дружелюбны к горячей загрузке. Более того, мы должны игнорировать ненужное ключевое слово const. Взгляните на следующий код:

const Container(
width: 100,
child: const Text(‘Hello World’)
);
Нам не нужно использовать const для виджета Text, поскольку const уже применяется к родительскому виджету.

Dart предлагает следующие правила Linter для const:

prefer_const_constructors
prefer_const_declarations
prefer_const_literals_to_create_immutables
Ненужный_const

  1. Вы можете объявить несколько переменных с помощью сокращения — (int mark =10, total = 20, amount = 30;)Убедитесь, что используете переменные класса final/const, когда есть такая возможность.Старайтесь не использовать необязательные закомментированные коды. Создавайте приватные переменные и методы, когда это возможно.Создавайте различные классы для цветов, стилей текста, размеров, постоянных строк, продолжительности и так далее.Создавайте константы API для ключей API.Старайтесь не использовать ключевые слова await внутри блокаСтарайтесь не использовать глобальные переменные и функции. Они должны быть связаны с классом.Проверьте анализ dart и следуйте его рекомендациямПроверьте подчеркивание, которое предлагает советы по исправлению ошибок или оптимизацииИспользуйте _ (подчеркивание), если значение не используется внутри блока кода.//DosomeFuture.then((_) => someFunc());

//Не делайте этого
someFuture.then((DATA_TYPE VARIABLE) => someFunc());
Магические числа всегда имеют правильные названия для удобочитаемости.
//Do
final _frameIconSize = 13.0;
SvgPicture.asset(
Images.frameWhite,
высота: _frameIconSize,
width: _frameIconSize,
);

//Не делайте этого
SvgPicture.asset(
Images.frameWhite,
высота: 13.0,
width: 13.0,
);
Отлично, вот и все
Итак, речь шла о лучших практиках разработки Flutter, которые относительно облегчают работу каждого разработчика Flutter.

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

Оцените статью
devanswers.ru
Добавить комментарий