Узнайте, почему компании из списка Fortune 500 выбирают нас в качестве партнера по разработке программного обеспечения. Исследуйте наш портфель. Проверено более 2500 проектов. Есть идея проекта, чтобы поделиться с нами? Давай поговорим.
Узнайте, почему компании из списка Fortune 500 выбирают нас в качестве партнера по разработке программного обеспечения. Исследуйте наш портфель. Проверено более 2500 проектов. Есть идея проекта, чтобы поделиться с нами? Давай поговорим.
Flutter best practices

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

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

Лучшие практики для разработки приложений

Здесь вы узнаете лучшие практики для разработчиков Flutter по улучшению качества кода, читаемости, ремонтопригодности и производительности.

1.Сделать функцию сборки чистой

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

  • Маршруты Pop/Push
  • Размер экрана, как правило, из-за внешнего вида клавиатуры или изменения ориентации
  • Родительский виджет воссоздал своего ребенка
  • Наследуемый виджет зависит от (класс. (контекст) шаблона) изменения

Избегайте:

@override
Widget build(BuildContext context) {
  return FutureBuilder(
    future: httpCall(),
    builder: (context, snapshot) {
      // create some layout here
    },
  );
}

Должно быть вот так:

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

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

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: future,
      builder: (context, snapshot) {
        // create some layout here
      },
    );
  }
}

2. Понимание концепции ограничений в флаттере

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

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

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

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

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

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

3. Умное использование операторов для уменьшения количества линий для выполнения

  • Используйте оператора каскадов

Если предполагается, что мы выполняем последовательность операций на одном и том же объекте, то мы должны выбрать оператора Каскадов.

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

//Do not
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];

//Do not
var y = [4,5,6];
var x = [1,2];
x.addAll(y);
  • Используйте операторов Null safe (??) и Null aware (?.).

Всегда используйте операторы ?? (если нет) и ?. (не знающие) вместо нулевых проверок в условных выражениях.

//Do 	
v = a ?? b; 
//Do not
v = a == null ? b : a;

//Do
v = a?.b; 
//Do not
v = a == null ? null : a.b;
  • А.недействительно использовать «как» оператор вместо этого, использовать «является» оператором

В целом, as Если забрасывать заброски невозможно, то для предотвращения заброса заброса за исключением может использоваться:is`.

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

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

4.Использовать потоки только при необходимости

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

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

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

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

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

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

abstract class MyBloc {
  Sink foo;
  Sink bar;
}

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

class _MyWigetState extends State<MyWiget> {
  MyBloc bloc;

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

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

5.Написать тесты на критические функциональные возможности

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

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

Единичные и виджетные тесты являются лучшими вариантами с самого начала, и это совсем не утомительно по сравнению с интеграционными тестами.

6. Используйте сырую нить.

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

//Do
var s = r'This is demo string  and $';

//Do not
var s = 'This is demo string \ and $';

7. использовать относительный импорт вместо абсолютного импорта;

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

//Do
import '../../themes/style.dart';

//Do not
import 'package:myapp/themes/style.dart';

8. Использование SizeBox вместо контейнера в флаттере

Существует несколько случаев использования, когда вам потребуется использовать заполнитель. Вот идеальный пример ниже:

_isNotLoaded? Контейнер(): YourAppropriateWidget();

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

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

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

return _isNotLoaded ? SizedBox() : YourAppropriateWidget();

9. Используйте вместо печати журнал.

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

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

//Do
log('data: $data');

//Do not
print('data: $data');
  • Используйте тройного оператора для однострочных случаев.
String alert = isReturningCustomer ? 'Welcome back to our site!' : 'Welcome, please sign up.';
  • Используйте условие вместо троичного оператора для случая, как ниже.
Widget getText(BuildContext context) {
    return Row(
        children:
        [
            Text("Hello"),
            if (Platform.isAndroid) Text("Android") (here if you use ternary then that is wrong)
        ]
    );
}
  • Всегда старайтесь использовать виджеты const. Виджет не изменится, когда заданный вызов State мы должны определить как постоянный. Он будет препятствовать перестроению виджета, чтобы он обновлял производительность.
//Do
const SizedBox(height: Dimens.space_normal)

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

10.Не инициируйте переменные в явном виде.

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

//Do
int _item;

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

//Do not
var item = 10;
final car = Car();
const timeOut = 2000;

11. Используйте ключевое слово const, когда это возможно

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

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

const Container(
  width: 100,
  child: const Text('Hello World')
);

Мы не требуем использовать const для виджета Text, так как const уже применяется к родительскому виджету.

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

prefer_const_constructors
prefer_const_declarations
prefer_const_literals_to_create_immutables
Unnecessary_const

12. Некоторые косметические моменты, которые следует иметь в виду

  • Никогда не отказывайтесь обернуть свои виджеты корня в безопасную зону.
  • Можно объявить несколько переменных со ярлыком - (int mark =10, total = 20, amount = 30);
  • Используйте переменные класса «конст»/«финал» всякий раз, когда есть возможность.
  • Старайтесь не использовать необязательные комментируемые коды.
  • По возможности создайте частные переменные и методы.
  • Создавайте различные классы для цветов, стилей текста, размеров, постоянных строк, продолжительности и так далее.
  • Разработайте константы API для ключей API.
  • Не используйте ожидающие ключевые слова внутри блока
  • Постарайтесь не использовать глобальные переменные и функции. Они должны быть связаны с классом.
  • Проверяйте анализ дарта и следуйте его рекомендациям
  • Проверьте подчеркивание, которое предлагает советы по Typo или оптимизации
  • Используйте _ (подчеркните), если значение не используется внутри блока кода.
//Do
someFuture.then((_) => someFunc());

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

//Do not
SvgPicture.asset(
Images.frameWhite,
height: 13.0,
width: 13.0,
);

Хорошо, вот мы и здесь.

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

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

Нашел этот пост проницательным?Не забудьте поделиться им с вашей сетью!
  • facebbok
  • twitter
  • linkedin
  • pinterest

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