Лучшие практики Flutter
В этом разделе будут представлены лучшие практики и стандарты кодирования при разработке на Flutter.
Стандарты кода
Соглашения об именовании
| Type | Правила | Пример |
|---|---|---|
| Имя класса | UpperCamelCase | MyHomePage |
| Функции/Переменные | lowerCamelCase | userName, getData |
| Константы | Верхний Camel Case + префикс k | kMaxCount |
| Файл | Нижний регистр + подчеркивание | my_home_page.dart |
Пример: правильное именование
// Имя класса - UpperCamelCase
class UserProfilePage extends StatelessWidget {}
// Функция - lowerCamelCase
void fetchUserData() {}
// Переменная - lowerCamelCase
String userName = 'Zhang San';
// Константы - префикс k
const int kMaxRetryCount = 3;
const String kAppName = 'My App';
// Перечисление - UpperCamelCase
enum AppState { loading, success, error }
// Имя файла - snake_case
// user_profile_page.dart
class UserProfilePage extends StatelessWidget {}
// Функция - lowerCamelCase
void fetchUserData() {}
// Переменная - lowerCamelCase
String userName = 'Zhang San';
// Константы - префикс k
const int kMaxRetryCount = 3;
const String kAppName = 'My App';
// Перечисление - UpperCamelCase
enum AppState { loading, success, error }
// Имя файла - snake_case
// user_profile_page.dart
Оптимизация производительности
1. Избегайте ненужных перестроек
Пример: Использование const-конструктора
// Рекомендуется: используйте const для уменьшения перестроек
const Text('Hello') // Не будет перестраиваться
const SizedBox(width: 10)
// Избегайте: каждая сборка создаёт новый объект
Text('Hello') // Будет перестраиваться
// Используйте const в списках
ListView(
children: const [
Текст('A'),
Текст('B'),
Текст('C'),
],
)
const Text('Hello') // Не будет перестраиваться
const SizedBox(width: 10)
// Избегайте: каждая сборка создаёт новый объект
Text('Hello') // Будет перестраиваться
// Используйте const в списках
ListView(
children: const [
Текст('A'),
Текст('B'),
Текст('C'),
],
)
2. Используйте ключи для оптимизации производительности списка
Пример: правильное использование ключей
// Добавьте уникальные ключи к элементам списка
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
key: ValueKey(items[index].id), // Используйте уникальные идентификаторы в качестве ключей
title: Text(items[index].name),
);
},
)
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
key: ValueKey(items[index].id), // Используйте уникальные идентификаторы в качестве ключей
title: Text(items[index].name),
);
},
)
3. Ленивая загрузка элементов списка
Пример: использование ListView.builder
// Рекомендуется: используйте builder для ленивой загрузки
ListView.builder(
itemCount: 1000, // Обязательно использовать для больших списков
itemBuilder: (context, index) {
return ListTile(title: Text('Item $index'));
},
)
// Избегайте использования children для построения больших списков
ListView(
children: List.generate(1000, (i) => Text('Item $i')),
)
ListView.builder(
itemCount: 1000, // Обязательно использовать для больших списков
itemBuilder: (context, index) {
return ListTile(title: Text('Item $index'));
},
)
// Избегайте использования children для построения больших списков
ListView(
children: List.generate(1000, (i) => Text('Item $i')),
)
Структура проекта
Пример: рекомендуемая структура проекта
// lib/
// ├── main.dart # входной файл
// ├── app.dart # конфигурация приложения
// ├── core/ # основная функциональность
// │ ├── constants/ # константы
// │ ├── theme/ # тема
// │ ├── utils/ # вспомогательные классы
// │ └── extensions/ # расширения
// ├── data/ # слой данных
// │ ├── models/ # модели данных
// │ ├── repositories/ # Репозитории
// │ └── services/ # Сетевые сервисы
// ├── domain/ # Доменный слой
// │ └── entities/ # Сущности
// ├── presentation/ # Слой представления
// │ ├── pages/ # Страницы
// │ ├── widgets/ # Виджеты
// │ └── providers/ # Управление состоянием
// └── routes/ # Маршруты
// ├── main.dart # входной файл
// ├── app.dart # конфигурация приложения
// ├── core/ # основная функциональность
// │ ├── constants/ # константы
// │ ├── theme/ # тема
// │ ├── utils/ # вспомогательные классы
// │ └── extensions/ # расширения
// ├── data/ # слой данных
// │ ├── models/ # модели данных
// │ ├── repositories/ # Репозитории
// │ └── services/ # Сетевые сервисы
// ├── domain/ # Доменный слой
// │ └── entities/ # Сущности
// ├── presentation/ # Слой представления
// │ ├── pages/ # Страницы
// │ ├── widgets/ # Виджеты
// │ └── providers/ # Управление состоянием
// └── routes/ # Маршруты
Обработка ошибок
Пример: Глобальная обработка ошибок
void main() {
// Глобальный перехват исключений
FlutterError.onError = (details) {
// Логирование ошибки
print('Flutter Error: ${details.exception}');
// Отправить ошибку на сервер
reportError(details.exception);
};
// Перехват исключений Zone
runZonedGuarded(() {
runApp(const MyApp());
}, (error, stackTrace) {
print('Ошибка зоны: $error');
reportError(error);
});
}
// Глобальный перехват исключений
FlutterError.onError = (details) {
// Логирование ошибки
print('Flutter Error: ${details.exception}');
// Отправить ошибку на сервер
reportError(details.exception);
};
// Перехват исключений Zone
runZonedGuarded(() {
runApp(const MyApp());
}, (error, stackTrace) {
print('Ошибка зоны: $error');
reportError(error);
});
}
Другие расширенияСледование лучшим практикам делает код более поддерживаемым, повышает производительность и уменьшает количество ошибок в продакшене.