Оглавление · нативных (ios swift/objectivec) и...
TRANSCRIPT
7
Оглавление
Об авторе . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
О техническом рецензенте (обозревателе) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
О переводе . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Благодарности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Введение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
ГЛАВА 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Медитации над бездной . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18Что за (глупое) название? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19Dart: Язык богов? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21Виджеты окружают! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23Ближе к делу: плюсы и Минусы Flutter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .27Хватит болтать, начинаем практику с Flutter! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Flutter SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30Android Studio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Типичное приложение «Hello, World!» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32Горячая перезагрузка: вот что я люблю! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40Базовая структура приложения Flutter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42Еще парочка моментов «под прикрытием» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44Итого . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
ГЛАВА 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
МГНОВЕННОЕ РУКОВОДСТВО ПО DART . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Вещи, которые вы должны знать . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46Все о комментариях – без лишних комментариев . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .47Все меняется: переменные . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49Ну он и тип . . . типы данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51Перечисления – если одного значения мало! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56А ты его точно знаешь? Ключевые слова «as» и «is» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .57Плыть по течению: управление логикой потока команд . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .57Больше, чем ничто: void . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59Операторы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60Коротко про ООП в Dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63Кое-что о функциях . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71Что такое Assertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
8
Вне времени: асинхронность . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74Тсс, тихо! Библиотеки (и видимость) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75Для тебя я сделаю исключение: обработка исключений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .77У меня есть сила: генераторы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78Мета-Dart: метаданные . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80Пообобщаемся? Дженерики, или обобщения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
Подведем итоги . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
ГЛАВА 3 СКАЖИ ПРИВЕТ МОЕМУ МАЛЕНЬКОМУ ДРУГУ FLUTTER: ЧАСТЬ I . . . . . . . . . . . . . . . . . . . . . . 83
Набор виджетов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83Layout (Компоновка) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83Навигация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94Ввод данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103Диалоговые и всплывающие окна . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Подведем итоги главы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
ГЛАВА 4 СКАЖИ ПРИВЕТ МОЕМУ МАЛЕНЬКОМУ ДРУГУ FLUTTER . ЧАСТЬ II . . . . . . . . . . . . . . . . . . . . .123
Виджеты стиля . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123Theme и ThemeData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124Opacity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125DecoratedBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125Transform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
Анимации и переходы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127AnimatedContainer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127AnimatedCrossFade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128AnimatedDefaultTextStyle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130Несколько других: AnimatedOpacity, AnimatedPosition, PositionTransition, SlideTransition, AnimatedSize, ScaleTransition, SizeTransition и RotationTransition . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
Drag и Drop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131Просмотр данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133DataTable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135GridView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137ListView и ListTile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Остальные виджеты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140CircularProgressIndicator (CupertinoActivityIndicator) и LinearProgressIndicator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141Icon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141Image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143Chip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145FloatingActionButton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146PopupMenuButton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Базовые библиотеки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149Основные библиотеки фреймворка Flutter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
9
Библиотеки Dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153Вспомогательные библиотеки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
Итого . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
ГЛАВА 5 FLUTTERBOOK . ЧАСТЬ I . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .158
Что мы делаем? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158Старт проекта . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160Конфигурации и библиотеки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161Структура UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162Структура кода приложения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163Отправная точка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163Глобальные утилиты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166Управление состоянием . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168Начнем с простого: заметки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
Точка отсчета: Notes .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172Модель: NotesModel .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174Слой базы данных: NotesDBWorker .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175Экран списка: NotesList .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179Экран ввода: NotesEntry .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
Что в итоге . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
ГЛАВА 6 FLUTTERBOOK . ЧАСТЬ II . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .192
Сделаем это: задачи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192TasksModel .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192TasksDBWorker .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193Tasks .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193TasksList .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193TasksEntry .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
Назначим свидание: Appointments (Встречи) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197AppointmentsModel .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197AppointmentsDBWorker .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198Appointments .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198AppointementsList .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198AppointmentsEntry .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Как с вами связаться: контакты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206ContactsModel .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206ContactsDBWorker .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207Contacts .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207ContactsList .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207ContactsEntry .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
Подведем итоги . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
ГЛАВА 7 FLUTTERCHAT . ЧАСТЬ I: СЕРВЕР . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .218
Можем ли мы это построить? Да, мы можем! Но . . . что «это»?! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
10
Node . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219Сохранение линий связи открытыми: socket .io . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222Код сервера FlutterChat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
Два Bits of State и Object заходят в Bar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227Поймай меня, если сможешь: сообщения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228Заходим в парадную дверь: проверка пользователей . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
Итого . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
ГЛАВА 8 FLUTTERCHAT . ЧАСТЬ II: КЛИЕНТ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .239
Model .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239Connector .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
Связанные с сервером функции сообщений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245Связанные с клиентом обработчики сообщений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
main .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249LoginDialog .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
Вход для существующих пользователей . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255Home .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257AppDrawer .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258Lobby .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260CreateRoom .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
Строим форму . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266UserList .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268Room .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
Меню . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272Содержимое главного экрана . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275Приглашение или исключение пользователей . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
Итого . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
ГЛАВА 9 FLUTTERHERO: ИГРА FLUTTER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .282
История такова . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282Базовая компоновка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283Структура каталога и исходные файлы компонентов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284Конфигурация: pubspec .yaml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286Класс GameObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287Расширение GameObject: класс Enemy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291Расширение GameObject: класс Player . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293Место, где все начинается: main .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296Основной игровой цикл и основная игровая логика . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
Начнем . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301Первичная инициализация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302Коротко об анимациях во Flutter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303Сброс состояния игры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305Основной игровой цикл . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307Проверка на наличие столкновений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
11
Размещение объекта в случайной точке . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312Передача энергии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
Все под контролем: InputController .dart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315Что дальше? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
УКАЗАТЕЛЬ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .318
12
Об авторе
Фрэнк Заметти – автор ряда популярных технических книг, был програм-мистомоколо40лет,25изкоторыхзанималсяэтимпрофессионально,надожеемубылочто-токушать.Втевременанаеговизиткезначилосьархитектор,хотяонпродолжалписатьтупойкодикаждыйденькрутилсякакмог.Фрэнк–первоклассныйгик:еслионнезаставляетсвойкомпьютервыполнятьприка-зы(скореевсего,дьявольские),тозанятпросмотром,чтениемилинаписаниемнаучнойфантастики,моделированиемрельсотрона,катушкиТеслыилилю-бойдругойштуковины,способнойприкончитьеговлюбоймомент;онлюбитбезпричиныцитировать «Вавилон 5», «Властелин колец», «Хроники Риддика» или«Настоящих гениев»,атакжеигратьвкомпьютерныеигры.ЕщеФрэнк–рок-музыкант (клавишник) и заядлый любитель пиццы и других углеводов.Унегоестьжена,собакаинесколькодетей.Еслиподвестиитогегокрутости,тоонтот,ктовсегдаготоввоскликнуть«Стобоймоймеч!»(нуда,обычногикицитируют«Властелин колец»безочевиднойпричины).
13
О техническом рецензенте (обозревателе)
ГерманванРосмаленработаетразработчикомиархитекторомпрограммногообеспечениядляDeNederlandscheBankNV,центрального банкавНидерландах.Заегоплечамиболее30летопытаразработкиприложенийнараз-ныхязыкахпрограммирования.Германбылвовлеченвсозданиеприложенийдлямейн-фреймов, десктопов, серверов, веб-браузе-ровисмартфонов.Последние4годаонзани-мается в основномразработкойна .NET/C#иAngularпосле15летработысJava.
Германживет в маленьком городке Пей-наккервНидерландахсосвоейженойЛизбети детьми Барбарой, Леони и Рамоном. На-равнесразработкойсофтавсвободноевре-мя Фрэнк тренирует женскую футбольнуюкомандунапротяжениипоследних10лет.
И конечно же, он болеет за Фейеноорд(футбольныйклубизгородаРоттердамвНи-дерландах,которыйсчитаетсяоднимизве-дущихклубовстраны)!
14
О переводе
ДаннаякнигабылапереведенаспециалистамикомпанииBinwell,атакжедей-ствующими преподавателями Binwell University. Надеемся, что наши книгиипереводыпозволятвамлегкоосвоитьновыетехнологии,атакжепостроитьуспешнуюкарьерувсфереинформационныхтехнологий.
Надпереводомкниги«Flutterнапрактике»работали:
Артем Тищенко, переводчик–руководительнаправленияMobileвком-панииBinwell,специалиствразработкенативных(iOSSwift/ObjectiveC),атак-жекроссплатформенных(XamarinиFlutter)мобильныхприложений.МенторBinwell University, соавтор ряда популярных статей для Microsoft DeveloperBlogsиХабрахабры.
Вячеслав Черников, редактор перевода–руководительразработкивком-панииBinwell,руководительBinwellUniversity.РаботаетвсфереMobileираз-работкиПОс2005года.СоздавалприложенияиигрыдляiOS,Android,Symbian,WindowsMobile,Meego,LinuxиWindowsUWP.Имеетбогатыйопытразработкинативных(iOSSwift/ObjectiveC)икроссплатформенных(Xamarin,Qt,PhoneGap/HTML5,Unity)мобильныхприложений.Авторкниги«РазработкамобильныхприложенийнаC#дляiOSиAndroid»(ДМКПресс,2020),атакжепопулярныхстатейдляХакера,Хабрахабры,MicrosoftDeveloperBlogs,спикер,преподава-тельинемного[безумный]ученый.
ТакжевыражаемблагодарностьАлександру РыжковуиСергею Селютину запомощьскорректировками.
15
Благодарности
Есливыникогданезанималисьнаписаниемкниги,тояоткроювамсекрет:написаниесамойкниги–этолишьмалаячастьбольшойработынадней.Ино-гда,мнекажется,наименьшаячасть!
Поэтомуяхочупоблагодаритьвсех,ктоусердноработалипомогалсэтимпроектом(неважно,личноилисредактурой),включаяНэнсиЧен,ЛуисаКор-ригана,ДжеймсаМаркхэма,ГерманаванРосмалена,ВэлмодаСпараиДанишаКумара.Есливашегоименинетвсписке,хотяонодолжноздесьбыть,яприно-шусвоиискренниеизвиненияиблагодарювас.
Такжея хотелбыпоблагодаритьЛарсаБакаиКаспераЛанга за созданиеDart, довольно элегантногои оченьприятного в использовании языкапро-граммирования,лежащеговосновеFlutter.Говорюкакчеловек,которыйсо-здалсвойсобственныйязыкинаборинструментовдлянегомноголетназад,яочень-оченьценюто,чтовысделали,ребята.Честьвамислава!
РаботанадкнигойпоFlutterтребуетотменяблагодарностипочтивсейко-мандеразработчиковэтогофреймворка.Я занимаюсьмобильнойразработ-койоколо20лет(посмотритенаetherient.com,страницуProducts,аконкрет-ноEliminator–игра,которуюявыпустилв2001годудляплатформыPocketPC;яверю,чтоэтобыломоепервоемобильноеприложение,покрайнеймереперваяудачнаяпопытка),итогда,насколькоямогусудить,яиспользовалдо-статочномногоутилит,фреймворковибиблиотек.Учитываявесьэтотопыт,ямогусуверенностьюсказать,чтоFlutterдажеспервойверсиибылнаголовувышевсех.
Этопоразительно, сколькокомандаFlutter смогла сделать затакойотно-сительнокороткийпериодвремени,ибезихтяжелойработыябы,очевидно,ненаписалэтукнигу!ЯснетерпениемждувозможностивсебольшеибольшеиспользоватьFlutter,атакжемнеоченьинтересно,чтобудетсFlutterдальше!
16
Введение
Создание кроссплатформенных приложений, которые выглядят и работаюткакнативные,–сложнаязадачадажепослемногихлетработынадеерешени-ем.Выможетеписатьотдельныепрограммыдлякаждойплатформыипытать-сясделатьихдизайнмаксимальнопохожим.Нофактическиэтозначитнапи-сатьодноприложениенесколькораз.Заказчики,какправило,неготовызата-коеплатить!
Может, взятьHTML-страницу и использовать один итотже код для всехплатформ?Нотогдавыможетеостатьсявдуракахсточкизрениявозможно-стейсамогоустройства,неговоряужеотом,чтопроизводительностьчастона-ходитсянанизкомуровне(существуютспособыминимизированияпроблем,ноониникогданеисчезнутполностью).
Язанимаюсьэтимужевтороедесятилетие(серьезно!),поэтомуявиделта-коемногораз.Иеслиязамечунагоризонтеобразединорога,тобудусомне-ватьсядоконца.Однакоесли,подойдяпоближе,окажется,чтоединорогдей-ствительнореален?
Итак,япредставляювамединорога,которыйнасамомделесуществует,–Flutter!
БлагодаряталантливыминженерамизGoogleFlutter–этоплатформа,по-зволяющаяписать(болееилименее)кроссплатформенныйкод,которыйоди-наковоработаетнаAndroidиiOS,приэтомобеспечиваяпроизводительность,идентичную нативным приложениям. Flutter, созданный с использованиемсовременныхинструментовиметодовразработки,открываетпрограммистаммирмобильнойразработки,вкотором,даженепобоюсьсказать,веселорабо-тать!
ВэтойкнигевыпознакомитесьсFlutter,создавдвареальныхприложениявместо надуманных примеров, предназначенных лишь для демонстрациитехнологии.Наэтомпутивыузнаетемногореальныхтонкостей,включаяпро-блемы,скоторымиястолкнулся,ирешения,которыеянашел.ПриэтомвыполучитепрактическийопытреальногоиспользованияFlutter,которыйпод-готовитвасксозданиюсобственныхприложенийвбудущем.
Вытакжеузнаетето,каксоздаватьсерверныеприложениянаNode.jsиWebSockets. Эти бонусы являются полезным дополнением к описанию самогофреймворкаFlutterиязыкаDart.
Крометого,высможетесоздатьдополнительноетретьеприложение,кото-роеразительноотличаетсяотпервыхдвух,–игру!Да,мывместесоздадимигрунаFlutter,чтобырассмотретьтакиевозможности,которыередковстречают-сявнастоящихприложениях,нодаютвамвзглянутьнафреймворксразныхсторониполучитьмаксимумопыта.Этаиграможетбытьнесовсем«практич-ной»,ноигрывсегдаувлекательны,анемноговесельяникомунеповредит!
Дочитавдоконца,выполучитепредставлениеотом,чтотакоеFlutter,иувасбудетотличнаявозможностьсоздатьсвоеновоекрутоеприложениенаегооснове.
17
ВВЕДЕНИЕ
Есливыбыликомпьютернымэнтузиастомв80-хгодах,тонавернякапом-ните,каковоэтобыло–набиватьнасвоемкомпьютеремашинныйкодизжур-нальнойстатьив20страницмелкимшрифтом,чтобысыгратьвигруилиза-пуститьприложениедлясверкивашихдоходовирасходов(да,мыдействи-тельноэтоделали–былидажерадиостанции,транслировавшиеисходники,которыезатемкомпилировалисьвготовоеприложениеспомощьюспециаль-нойутилиты,подобнотомукаксейчаскодируетсязвукдляпередачипотеле-фоннойлинии).
Итак,преждечемначать,япредлагаювамзайтинавеб-сайтApress,найтиэтукнигуискачатьсебеисходныекодыпримеров.Этопозволитобойтисьбезстиранияпальцеввкровь,перепечатываялистингиизкниги!
Незабывайте,лучшийспособчему-тонаучиться–этоделать,поэтомуобя-зательноскачайтеиизменитепримерыподсебя,увидевсвоимиглазами,начтоэтиизмененияповлияют.Послепрочтениякаждойглавы,связаннойспри-ложением,заходитевисходныекодыипробуйтедобавитьоднуилидвесвоифункции,иядажедамвампарусоветов.Думаю,вскоревыпоймете,чтоблаго-дарявозможностямFlutterнебольшиеизменениямогутсущественноповлиятьнато,чтопоявляетсянаэкране.
Итак,приготовьтеськприятнойиинформативнойпоездкевмирFlutter!Янадеюсь,чтовампонравитсяэтакнигаивымногомунаучитесь.Этомоя
главнаяцель!Такчтоперекусите,сядьтевкреслепоудобнее,подготовьтено-утбукиприступайте.Васждутприключения!(Да,япрекраснопонимаю,какбанальноэтозвучит.)
Исходные коды примеров вы можете найти в репозитории на GitHub:https://github.com/Apress/practical-flutter.
18
ГЛАВА 1 .
FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
Поехали!Если вы спросите десять разных разработчиков мобильных приложений,
какониихразрабатываютдляAndroidиiOS,то,скореевсего,получитедесятьразныхответов.Ноэтоненадолго,благодарядебютантунаэтойсцене–Flutter.
Впервойглавемырассмотримразработкудлямобильныхустройств,то,какFlutterвписываетсявэтукартинуи,возможно,полностьюееменяет.Мынач-немснимработать,получимбазовоепредставлениеоязыкеифреймворке,атакжеподготовимпочвудлясозданияреальныхприложений.
Итак,давайтесразупоговоримотом,чтожетакоемобильнаяразработка.
Медитации над безднойРазработкасофта–этонепростаязадача!
Янехочуутомлятьвасисторией,нофактвтом,чтояначал,такилииначе,программироватьс7лет,аэтоозначает,чтоязанимаюсьэтимпочти40лет(около25изнихпрофессионально).Ямногоповидалимногосделал,ноглав-ное,чтояпонял:разработкасофта–этонепростаязадача.Конечно,некото-рыеотдельныезадачиипроектымогутбытьпростыми,новцеломэтодо-вольносложнаяработа,котороймызанимаемся!
Иэтомыещенеговоримомобильнойразработке,котораякудасложнее!Яначалразработкумобильныхприложенийпримернодвадесятилетияна-
зад,ещевовременаWindowsCE/PocketPCиPalmPilot(былиидругиеплатфор-мы,ноименноэтидвебылиединственныминастоящимиигрокаминарынке).Тогдавсебылонетакужиплохо,несмотрянаограниченныйнаборустройствивозможностейинструментовразработки,которымимырасполагали.Безус-ловно,использованиеэтихинструментовбылонетакимприятным,каксегод-ня,нобылвсегоодинспособразработкиприложенийдляPocketPC,одинспо-собразработкиприложенийдляPalmOS.Звучитнеочень,ноотсутствиевы-бораприводиткотсутствиюпутаницы,чтоявляетсяоднойизсамыхбольшихтрудностейвобластиразработкисофтанасегодняшнийдень.
Аеще,хотя сегодняэто считаетсянепопулярным,тогданебылопонятиякроссплатформенной разработки. Раньше приходилось писать код дважды,чтобыприложениеработалонаобеихплатформах.Учитываяразличиямеждуними,этобылонетак-топросто.
Стехпориндустриямобильныхустройствиприложенийпретерпеланема-лоэволюционныхизменений,подъемовипадений.Долгоевремяунасбыломногоплатформдляподдержки:Android, iOS,webOS,Tizen,WindowsMobileинесколькодругих,которыеядаженепомню.Всеэтовремяпереносприло-
19
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
жениймеждуплатформамибылнормой,посколькунебылохорошегокросс-платформенногоподхода,покрайнеймеребезсущественныхкомпромиссов.Да,современемсталопроще,потомучтоулучшилсяинструментарийдляна-тивнойразработки.AppleвыпустиласвойSDKдляiOSв2008году,аGoogleвы-пустилсвойAndroidSDKгодспустя–в2009-м.Намприходилосьразрабаты-ватьприложениядлякаждойплатформы,посколькуразработкаiOSосновананаязыкеObjective-C(сегоднячащенаязыкеSwift),втовремякакразработкаAndroidоснованапреимущественнонаязыкеJava(теперьчащенаKotlin).
Вконцеконцов,количествоплатформсталосокращаться.Насегодняшнийденьэто гонкаAndroidи iOS, хотяестьидругиеплатформы,которыечащевсегоиспользуютсятолькоприрешенииспецифическихзадач.Всвязисэтимприменениекроссплатформенныхинструментовстановитсяболеепривлека-тельным.
Наша прогрессивная эпоха интернета предлагает создавать приложенияспомощьютехнологий,лежащихвегооснове,икакрезультатполучитьпри-ложение,котороевыглядитиработаетпримерноодинаковонаобеихплатфор-мах(теоретическиинадругихтоже).Этосопровождаетсякомпромиссами,ко-торыесовременемминимизируются,новсеещесуществуют.Такиевещи,какпроизводительностьипрямойдоступквозможностям«железа»,всеещеслож-носовместитьсвеб-технологиями.
Однако,помимовеб-технологий,впоследниенескольколетмынаблюда-лирождениеидругихкроссплатформенныхинструментов,которыепозволя-ютнамнаписатьприложениеодинразиработатьснимпримерноодинакововразныхоперационныхсистемах.Популярныеварианты–CoronaSDK(впер-вуюочередьдляигр,нонеобязательно),Xamarin,PhoneGap(простовеб-тех-нологии, умно завернутые в собственный компонент WebView), TitaniumиSenchaTouch(опятьже,наосновевеб-технологий,носхорошимслоемаб-стракциинадним),может,ещенесколько.Такчтосейчаснамдоступномно-жестворазличныхвариантов,каждыйсосвоимиплюсамииминусами.
Атеперьвнимание!Нааренувыходитновыйконкурент,жаждущийубитьостальныхипоказатьединственныйверныйпутьнаписаниякроссплатфор-менныхмобильныхприложений:Flutter.
Да,этонемногоглупоеназвание...нознаете,мыможемзакрытьнаэтогла-за,потомучтопреимуществунеговышекрыши!
Что за (глупое) название?Flutter–этопродуктGoogle–ну,вызнаете,корпорации,котораяоснователь-ноконтролируетинтернет,хорошоэтоилиплохо(вслучаесFlutterядумаю,чтохорошо).ИзначальноэтотфреймворкродилсяподименемSkyв2015годунасаммитеразработчиковDart(незабудьтеэтослово,Dart,мыкнемускоровернемся).СначалаонработалтольконаоперационнойсистемеAndroidотса-могоGoogle,новскоребылпортированинаiOS,такчтосегодняонподдержи-ваетдвеведущиемобильныеоперационныесистемы.
20
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
ПервыеверсииFlutterбыливыпущенысразупослеегоанонса, акульми-нациейсталвыпускстабильнойверсии«Flutter1.0»4декабря2018года.По-слеэтогоFlutterбылготовкпрайм-тайму,ипришловремядляразработчиковзапрыгиватьнаборт!ПопулярностьFlutterможнобылобыохарактеризоватькакметеорическую,инаэтоестьвескиепричины.
Однаизнихзаключаетсявследующем:первоначальнозаявленнаяцельFlut-terили,покрайнеймере,однаизосновных,заключаласьвотрисовкепользова-тельскогоинтерфейсасоскоростью120кадроввсекунду.Googleосознавал,чтоотзывчивыйинтерфейсприведетпользователейввосторг,поэтомуэтафунк-циональностьилеглавосновуFlutter.Этоблагороднаяцель,которойдостига-ютлишьнемногиекроссплатформенныефреймворки(даженативныеинстру-менты–итечастоиспытываюттрудностисоскоростьюотрисовкисложногоинтерфейса).
Flutterтакжепредоставляет свои готовыекомпонентыпользовательскогоинтерфейса–вотличие,например,отXamarinиReactNative,оннеиспользуетнативныеконтролы.Другимисловами,когдавыхотите,чтобыFlutterотобра-зилкнопку,онрисуетеесам,анепроситобэтомоперационнуюсистему,какделаютдругиефреймворки.ИменноэтоиотличаетFlutterотостальныхипо-зволяетприложениямбытьодинаковыминаразныхплатформах.Важното,чтоновыекомпонентыпользовательскогоинтерфейса,иливиджеты(этосло-вотожезапомните,потомучто,какиDart,онотожескоровстретится),могутбытьдобавленывоFlutterбыстроилегко,небеспокоясьотом,поддерживаетлиихсамаоперационнаясистема.
ЭтотакжепозволяетFlutterпредоставлятьспецифическиенаборывидже-товвстилистикахMaterialиCupertino.ПервыйреализуетMaterialDesignотсамойGoogle–стильAndroidпоумолчанию.ПоследнийреализуетстильiOSотApple.
Flutterможноразделитьначетыреосновныечасти,включаяDart.Ясобира-юсьоставитьэтодоследующегораздела,такчтодавайтеперейдемковторо-мукомпоненту–основномудвижкуFlutter.ЭтотдвижоквосновномнаписаннаC++ииспользуетбиблиотекуSkia,такчтопроизводительностьотрисовкисравнимаснативной.Skia–этонебольшаяграфическаябиблиотекасоткры-тымисходнымкодом,котораятакженаписананаC++иимееточеньвысокуюпроизводительностьнавсехподдерживаемыхплатформах.
ВкачестветретьегоосновногокомпонентаFlutterпредоставляетунифици-рованный доступ к возможностям поддерживаемых операционных систем.Другимисловами,коддлязапускакамерынаiOSиAndroidбудетединым,адляэтогоможноиспользоватьготовыеметодыFlutter.
Последнийкомпонент–этовиджеты,но,какиDart,онитожезаслуживаютсобственногораздела,такчтовернемсякнимпозднее.
Есликоротко,тоFlutterсостоитизэтихчетырехмодулей,поэтомунетакужимногонужнознать,чтобыначатьнанемразрабатывать.Темнеменееяду-маю,чтонемногоуглубленноеизучениеинструментовникогданебудетлиш-ним.Надеюсь,высогласны!
21
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
ТеперьдавайтеболеедетальноразберемDartивиджеты,окоторыхговори-лиранее.
Dart: Язык богов?КогдаGoogleначалработатьнадFlutter,импредстоялоответитьнаглавныйвопрос:какойязыкпрограммированиявыбрать?Можетбыть,языквеб-раз-работки,такойкакJavaScript?ИлижеJava,языкAndroid?ИлирадиподдержкиiOSвыбратьSwift(вконцеконцов,Swiftявляетсяязыкомсоткрытымисход-нымкодом)?Возможно,что-товродеGoилиRubyбылобыхорошимвариан-том.Какнасчет«старойшколы»,C/C++?Аможет,попробоватьC#отMicrosoft(унеготожеоткрытыйисходныйкод)?
Яуверен,чтобыломноговариантов,новконцеконцовGoogleрешил(небезпричины!)использоватьязык,которыйонисоздалинескольколетназад:Dart.
ВсяследующаяглавапосвященаDart,поэтомусейчасявоздержусьотдета-лей,ноприведунебольшойпример:
import "dart:math" as math;
class Point { finalnumx,y; Point(this.x,this.y); Point.origin():x=0,y=0; numdistanceTo(Pointother){ vardx=x–other.x; vardy=y–other.y; returnmath.sqrt(dx*dx+dy*dy); }
Pointoperator+(Pointother)=>Point(x+other.x,y+other.y);}
voidmain(){varp1=Point(10,10);varp2=Point.origin();vardistance=p1.distanceTo(p2);print(distance);
}
Необязательносразудетальнопониматьвсё,чтовыздесьвидите.ТемнеменееесливыработалираньшеслюбымС-подобнымязыком,напримерJavaили JavaScript,тоготовпоспорить,чтовыбезпроблемвовсемразберетесь.ВэтомизаключаетсяглавноепреимуществоDart:большинствосовременныхразработчиковсмогутнаписатьипонятьподобныйкоддовольнолегко.
22
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
ПРИМЕЧАНИЕ. Интересно, что мы называем языки C-подобными, но сам C – потомок гораздо более старого языка ALGOL . Я думаю, что ALGOL никогда не получит заслуженного уважения, так что этой ре-маркой я выражаю всю любовь к нему!
Невдаваясьвовсемельчайшиеподробности(дляэтогопредназначенасле-дующаяглава),ядумаю,чтодаженебольшойсправкипоDartбудетдостаточ-но.GoogleсоздалDartещев2011году,иизначальноонбылпредставленнаконференции GOTO в Орхусе, Дания. Первый релиз 1.0 состоялся в ноябре2013года,примернозадвагодадовыпускаFlutter.ЗаDartстоитблагодаритьЛарса Бака (который разработал ещё и JavaScript-движокV8, используемыйвChromeиNode.js)иКаспераЛунда.
Dart–этолаконичныйязык,которыйбыстронабираетобороты,восновномблагодаряFlutter.Посколькуонсчитаетсяязыкомобщегоназначения,егоши-рокоиспользуютдлясозданиявеб-приложений,серверногокодаиприложе-нийIoT(InternetofThings,«интернетвещей»).Покаяписалэтуглаву,вышелопросотом,какиеязыкипрограммированиявызываютнаибольшийинтересразработчиковв2019году,опубликованныйJAXenter:https://jaxenter.com/poll-results-dart-word-2019-154779.html. В результате два языка заметноопередилиостальные:DartиPython,Dartвырвалсявперед.Dartиспыталнаи-большийроств2018году.ИхотяFlutter–почтинавернякаодинизсамыхпо-пулярныхвариантовегоиспользования,но,несмотрянаэто,Dartразвивает-сявовсехнаправлениях.Такчтобудьтеуверены,Dartнеобделенвниманием.
ТакчтожетакоеDart?Предыдущийпримеркодадемонстрируетглавныеключевыемоменты,окоторыхяхотелсказать:
• Dartполностьюобъектно-ориентирован;
• инфраструктураязыкавключаетвсебясборщикмусора,поэтомунетне-обходимостиследитьзапамятью;
• егосинтаксисоснованнаC,которыйподойдетбольшинствуразработчи-ков(темнеменее,какиулюбогодругогоязыкаспохожимсинтаксисом,унегоестьрядособенностей,которыепоначалумогутсбитьвасстолку);
• он поддерживает общие языковые конструкции, такие как интерфей-сы,наследование,абстрактныеклассы,шаблонныеклассы(generics,или«дженерики»)истатическуютипизацию;
• Dartвключаетпроверкусоответствиятипов.Этопозволяетиспользоватьалгоритмдляконтроляправильностивашегокода;
• онподдерживаетмногопоточность,такчтоодновременноможетиспол-нятьсянесколькоотдельныхпроцессов,обеспечиваявысокуюпроизво-дительность;
• Dartможеткомпилироватьсявнативныйкоддляповышенияпроизводи-тельности.ОннетолькокомпилируетсявкоддляпроцессоровARMиx86врежимеAheadOfTime(присборкеприложения),ноиможеттранслиро-
23
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
ватьсявJavaScript,атакжеподдерживаетдинамическуюкомпиляциювовремяисполнения(JustInTime);
• Dartпозволяетиспользоватьбольшойнаборрепозиториевсготовымиби-блиотеками,которыеобеспечиваютдополнительнуюфункциональностьдлявсего,чтоможетпонадобитьсяразработчикам;
• поддержкапопулярныхсредразработки,включаяVisualStudioCodeиIntelliJIDEA;
• ядроDartподдерживаетсоздание«слепков»(snapshots),которыепозво-ляютупаковатьвесьисполняемыйкод(нетольковашкод,ноибиблиоте-ки)вединыйдвоичныйфайл,чтоускоряетзапускприложения.
DartтакжезарегистрированвкачествемеждународногостандартаECMA-408,аегоактуальнуюспецификациювсегдаможнополучитьнасайтеwww.dartlang.org/guides/language/spec.
Какяужеотмечалранее,всявтораяглавабудетпосвященаDart,апокамыперейдемкследующейважнойтеме.
Виджеты окружают!Давайтевернемсякразговоруоглавномгостенашегошоу,Flutter,иконцеп-ции,котораялежитвегооснове,–виджетах.
Flutter–этоиестьвиджет.Когдая говорю,чтоон и есть виджет,яимеюввиду...ну...яимеюввиду,чтопочтивсевнемявляетсявиджетом(гораздосложнеенайтивоFlutterто,чтовиджетомне является!).
Чтожетакоевиджет,спроситевы?Эточастивашегопользовательскогоин-терфейса(хотяиневсевиджетыявноотображаютсянаэкране).Виджеттакжепредставляетсобойфрагменткода,например:
Text("Hello!")
…иэтотакжевиджет...
RaisedButton( onPress:function(){ //Сделайчто-нибудь. }, child:Text("Clickme!"))
...иэтотожевиджет...
ListView.builder( itemCount:cars.length, itemBuilder:(inContext,inNum){ returnnewCarDescriptionCard(card[inNum]); })
24
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
...инаконец,этовиджет:
Center( child:Container( child : Row( Text("Child1"), Text("Child2"), RaisedButton( onPress:function(){ //Dosomething. }, child:Text("Clickme") ) ) ))
Последнийпримеринтересентем,чтонасамомделеэтоиерархиявидже-тов:виджетCenter,авнемвиджетContainer,содержащийвиджетRow,кото-рый,всвоюочередь,содержитдочерниевиджетыTextикнопкуRaisedButton.
Неважно,чтоэтозавиджеты(хотяназванияихотличнохарактеризуют),главное, что всяиерархиявиджетов, которуювывидите, сама по себетакжесчитаетсявиджетомFlutter.
Да,воFlutterповсюдувиджеты!Виджетыокружают!Flutter–этоОпра[По-пулярнаяведущаяТВ-шоувСША.–Прим. перев.]вмирефреймворковпользо-вательскогоинтерфейса:вамнуженвиджет–выполучаетевиджет!Да,выпо-лучаетевиджет!ВыВСЕполучаетевииииииджеты!
Какясказалранее,воFlutterпрактическивсе–этовиджет.Естьочевидныевещи,окоторыхлюдидумают,употребляяслововиджетвконтекстепользо-вательскогоинтерфейса:кнопки,списки,изображения,полятекстовыхформивсетакоепрочее.Этовсевиджеты.НовоFlutter-то,чтовывиджетаминесчи-таете,этовсеещеони.Например,рамкавокругизображения,состояниеполятекстовойформы,текст,отображаемыйнаэкране,дажетема,которуюисполь-зуетприложение.
Врезультатемывидим,чтокодвоFlutter–этогигантскаяиерархиявид-жетов(иэтаиерархияимеетконкретноеимявоFlutter:WidgetsTree,«деревовиджетов»). Видите ли, большинство виджетов являются контейнерами, этоозначает,чтоонимогутиметьдочерниеэлементы.Некоторыевиджетымогутиметьтолькоодинтакойэлемент,втовремякакдругиемогутиметьмного.Итогдаукаждогоизнихможетбытьодинилинесколькодочернихэлементов,итакдалее,итакдалее!
ВсевиджетыявляютсяклассамиDart,иунихестьобязательноетребование:предоставитьметодbuild().Этотметоддолженвозвращать...подождите,по-дождите...другие виджеты!Естьоченьмалоисключенийизэтого,напримернизкоуровневыевиджеты,такиекаквиджетText,которыйвозвращаетприми-
25
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
тивныйтип(внашемслучае–String),нобольшинствовозвращаютодинилинескольковиджетов.Помимоэтоготребования,виджет–этостарыйдобрыйклассDart,которыйнеотличаетсяотклассавлюбомдругомобъектно-ориен-тированномязыке(заисключениемсинтаксиса).
ВиджетвоFlutterрасширяет(extends)одинизстандартныхклассов,кото-рыеонжеипредоставляет, что характернодляобъектно-ориентированнойпарадигмы.Расширенныйкласс (extendedclass)определяет, скакимвидже-томмыимеемделонафундаментальномуровне.Естьдвасамыхбазовыхклас-са,которыевыбудетеиспользовать,вероятно,99%времени:StatelessWidget иStatefulWidget.
Виджет,унаследованныйотStatelessWidget,неизменяетсяпослеотображе-нияиназываетсявиджетомбезсостояния,потомучтооннеимеетсостояния(логично).Такиевиджеты,какIcon(отображаетнебольшиеизображения)иText (отображаетстрокитекста),тоженазываютвиджетомбезсостояния.Примеромподобногоклассаможетбытьследующее:
classMyTextWidgetextendsStatelessWidget{ Widgetbuild(inContext){ returnnewText("Hello!"); }}
Да,здесьнетничегоособенного!В отличие от StatelessWidget, наследники базового класса StatefulWidget
изменяются, когда пользователь взаимодействует с ним. CheckBox, Slider,TextField–этовсеизвестныепримерывиджетовссостоянием(и,кстати,ког-давывидите,чтоонинаписанысбольшойбуквы,тоэтоозначает,чтояимеюввидуфактическиеименаклассовFlutter,анеобщиетермины).Когдавыкоди-руететакойвиджет,вамнужносоздатьдвакласса:самклассвиджетассостоя-нием(StatefulWidget)икласссостояния(State),связанныйсним.ВотпримервиджетаStatefulWidgetисвязанногоснимклассаState:
classLikesWidgetextendsStatefulWidget{ @override LikesWidgetStatecreateState()=>LikesWidgetState();}
classLikesWidgetStateextendsState<LikesWidget>{ intlikeCount=0;
voidlike(){ setState((){ likeCount+=1; }); }
@override
26
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ Widgetbuild(BuildContextinContext){ return Row( children:[ RaisedButton( onPressed:like, child:Text(‘$likeCount’) ) ] ); }}
Опятьже,янежду,чтовыполностьюпойметеэтоткод,таккакрасширятьзнанияпоDartмыначнемпозже.Ноявсёравносчитаю,чтовыприблизи-тельнопонимаете,чтоздесьпроисходит.Покрайнеймере,то,каккодвиджетаиегообъектсостояниявзаимодействуютисвязаны.Может,этонетакужоче-видно,нонебеспокойтесь,этоненадолго!
Возвращаяськвиджетамбезсостояния,следуетотметить,чтотермин«вид-жетбезсостояния»несовсемточен,потомучто,будучиклассомDart,которыйимеетсвойстваиинкапсулированныеданные,виджетыбезсостояниявне-которомсмыслеимеютсостояние.ОсновноеразличиемеждуStatelessWidgetи StatefulWidget заключается в том, что виджет без состояния (stateless) неумеетавтоматическиперерисовыватьсяприизмененииего«состояния»,тог-дакаквиджетссостояниемможет.Когдавиджетссостояниемизменяется,не-зависимооттого,чтовызываетизменение,возникаютопределенныесобытияжизненногоцикла.Когдасостояниевиджетаизменяется,топроисходитвызовопределенныхметодов,ионперерисовывается (еслинеобходимо,тоFlutterделаетэтоавтоматически)
Представьте:обатипавиджетовмогутиметьсостояние,ноFlutterраспозна-етиуправляеттолькоstateful-виджетом.Такимобразом,толькоStatefulWidgetможетбытьавтоматическиперерисованвответнавнешнеесобытие,иэтокон-тролируетсясамимFlutter,авамненужнопрописыватькодвручную.
Возможно,теперьвызахотитепользоватьсятольковиджетамиссостояния-ми,таккакэтосократитвашуработу,новскоревыпоймете,чтоэтонесовсемтак.Врезультатевыпредпочтетевиджетбезсостояния,дажееслисейчасэтокажетсявамнелогичным.Нодавайтеопустимэтоненадолго.
Естьдваважныхаспекта,накоторыевыуженавернякаобратиливнимания.Во-первых,пользовательскийинтерфейспостроенпутемсозданиявиджетов.Этоприводиткдеревувиджетов,окоторомяупоминалранее.Втовремякаккодсамихвиджетовявляетсяобычнымклассом,важноучитыватьвложенностьирасположениевиджетовнаэкране.Этоважнопотому,чтобольшинствовид-жетовFlutterсамипосебедовольнопросты,итолькочерезкомпозициювымо-жетесоздатьсложныйпользовательскийинтерфейс.Дажеотносительнотри-виальныйпользовательскийинтерфейссодержитвсебецелуюгруппувидже-тов.
27
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
Во-вторых, пользовательский интерфейс во Flutter описывается напря-муювкоде.Язнаю,чтоэтокажетсяочевидным,нозадумайтесьвотнадчем:для пользовательского интерфейса Flutter нет отдельного языка разметки,какHTMLввеб-разработке.Преимуществозаключаетсявтом,чтоестьтоль-коодинязыкдляизучения,единаяпарадигмадлявосприятия.Может,снача-лаэтоинезаметно,ноэтоважноепреимуществоFlutterнадконкурирующимивариантами.
Покаэтовсе,чтонужнознатьовиджетах.Мыизучимкаталогвиджетовболееподробноначинаясглавы3,и,конечно,мырассмотримиспользованиекаждо-гоизнихвглаве4,когдабудемделатьприложениясними.Вконцеконцов,выполучитехорошиезнанияонаиболеераспространенныхвиджетахFlutter,атакжедругие,неменееполезныебазовыенавыкииспользованияисозданиявиджетоввцелом.
Ближе к делу: плюсы и Минусы FlutterКакислюбымфреймворком,намкакхорошимразработчикамнужнооценитьпреимуществаиподводныекамниFlutter.ВоFlutterестьито,идругое,яженебудубросатьсявкрайностииговорить,чтоэто«панацеяотвсехбед»илижеполныйпровал.Иесликто-тоговоритвам,чтоонидеален,товампростопускаютпыльвглаза.ВоFlutterестьсвоинедостатки,нояскромнопредполо-жу,чтоестьдовольномногопроектовиразработчиков,длякоторыхонможетстатьотличнымвариантом,еслинелучшим.
ДавайтеужеобсудимвсеплюсыиминусыFlutter,атакжесравнимегоскон-курентами.
• За:горячаяперезагрузка(hotreload)–кнейявернусьпослетого,какмыизучимнастройкуокруженияивзглянемнапервыйпримерприложения–высамиубедитесь,чтоэтобольшоепреимуществоFlutter.ReactNativeтак-же включает возможность горячей перезагрузки, особенно если вы ис-пользуетестороннийкомпонентExpo.ОднаковоFlutterэтафункциональ-ностьреализованаболеекачественноистабильно.Немногиефреймворки,даженативные,могутпохвастатьсяподобнымивозможностями.
• Против: только для мобильных устройств. На момент написания этойкнигиможнобылоиспользоватьFlutterтолькодляразработкимобиль-ныхприложенийiOSиAndroid.ЕсливыполюбитеFlutter,тобудетеразо-чарованытем,чтонесможетеиспользоватьегодляразработкивсехва-шихприложений.Темнеменееобратитевнимание,чтояначалсослов«намоментнаписания».Этопотому,чтосвысокойстепеньювероятностиFlutterтакжебудетдоработандляподдержкиприложенийдлявеб-брау-зеров,Windows,macOS,Linuxидругихплатформ.[Ида!Flutterпортиро-валинавеб-браузерыидесктопныеплатформы,хотяпроцессэтотещетольконачался.–Прим. перев.]
28
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
• За:да,ондействительнокроссплатформенный–вашиприложенияFlutterбудуткорректноработатьнаiOSиAndroid(ивконечномитогепреемни-кеAndroid–Fuchsia).Flutterпоставляетдванаборавиджетовизкоробки,одиндля iOSиодиндляAndroid,поэтомувашиприложениямогуткаквыглядетьодинаковонаобеихплатформах,такиучитыватьстилистикуцелевойоперационнойсистемы.
• Против: веб-разработчики, не привыкшие видеть описание логикипо-веденияиразметкипользовательскогоинтерфейсаводномклассе,какправило,оченьэмоциональнореагируютнапримерыFlutter.Длясравне-ния,ReactNative,укотороготакжеводномклассеописываетсяилогикаиразметка,первоевремястрадалотподобныхжалоб,нопотомразработ-чикипривыкли.
• За:Dart–простойимощный,объектно-ориентированныйистроготи-пизированный,чтопозволяетразработчикамбытьоченьпродуктивны-ми,быстрымииделатьменьшеошибок.Кактольковыпройдететерни-стыйначальныйпутьобучения,вампонравитсяDart,особенновсравне-ниисJavaScript,Objective-CилиJava.
• Против:Google–япричисляюэтокнедостаткам,ивыопределенномо-жетесомнойнесогласиться(раньшеячастоспорилобэтомсамссобой).НекоторыелюдичувствуютсебянекомфортнооттакогоконтроляGoogleнадинтернетом,дажееслиGoogleэтимактивнонепользуется.Когдавыдоминируете,то,какправило,многоеконтролируете.Темнеменеенеко-торыелюдиопасаются,чтоGoogleнаращиваетоборотыинаещеодномнаправлении–длянихэтоможетбытьужеслишком.Другие,конечно,посмотрятнаэтоискажут,какздорово,чтогигантподдерживаеттакуюзамечательную технологию. Так что этот «недостаток» можно назватьспорным.Ивыбратьсторонуможететольковы.
• За:виджеты–Flutterпредоставляетразработчикамбогатыйнаборвидже-тов,иэтогоможетбытьвполнедостаточнодляпостроениялюбогопри-ложения.Вытакжеможетесоздаватьисвойсобственныйвиджет(наса-момделевывсегдабудететакделать,неважно,накакомуровне),идажеиспользоватьмногиесторонниевиджеты,дабырасширитьвозможностиприложения.Этивиджетытакжепростывиспользовании,каките,чтонампредлагаетсамFlutter.
• Против: дерево виджетов (widgets tree) может стать недостатком, ведьиногда вы будете сталкиваться с очень глубоко вложенной иерархией,иразобратьсясоструктуройкодастанетнетак-топросто.Сразвитиеминтернетамыкэтомуужепривыкли,потомучтоHTMLсампосебеявля-етсядревовидным,однакопосколькупрактическивсевоFlutterявляетсявиджетами,иерархияиногдаможетбытьдажеглубжеHTML,астилькодаDart выглядит сложнее. Конечно, естьметоды, позволяющие это упро-стить.Ноонихярасскажупозженапримерахреальногокода,ида,это
29
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
всеещенедостаток,потомучтовыдолжныосознаватьегоиуметьрабо-татьснимсамостоятельно.НиFlutter,ниDartнепредложатвамподска-зокврешении.
• За:инструменты–каквыувидитевследующемразделе,настроитьсре-дуразработкидляFlutterоченьлегко.Темнеменеевыможетевыйтизапределыэтойбазовойсредыииспользоватьмногиеужепривычныеваминструменты.
• Против:реактивноепрограммированиеиуправлениесостоянием–Flut-terобычносчитаетсяреактивным(reactive).Методbuild(),которыйвывиделиранее,принимаетвкачествеаргументатекущеесостояние,ато,чтоонвозвращает,–этовизуальноепредставлениеэтоговиджета,наос-новеобновленногосостояния.Когдаобновляетсясостояние,виджет«ре-агирует»наэтоиобновляетсебяспомощьюповторноговызоваметодаbuild().Всёэто–стандартныймеханизмFlutterитиповойжизненныйциклвиджета.Сравнитеэтос«нереактивными»подходами,когдавысоз-даетевиджет,азатемсамостоятельновызываетенужныеметодыдляегомодификацииилиобновления.Вцеломреактивнаяпарадигмадовольноудобна,хотядляFlutterонаможетбытьинедостатком,потомучтоиногдаэтоусложняетпростыевещи(высамиувидитеподобныепроблемывпо-следующихглавах,атакженаучитесьснимисправляться).Сэтимсвяза-наисложностьуправлениясостояниями,котораяявляетсянедостаткомFlutterвтомсмысле,чтонетканоническиправильногоинеправильно-госпособаэтоделать.Существуетмножествоподходов,иукаждогоестьсвоиплюсыиминусы,авамнужнобудетрешить,чтолучшесоответству-етвашимпотребностям(ида,ябудупредлагатьто,чтосчитаюхорошимподходом).Googleработаетнадтакимканоничнымподходомпрямосей-час,нопокаоннеготов,ябудурассматриватьотсутствиеопределенногопутикакнедостаток(хотянекоторыесчитаютгибкостьпреимуществом!).
• За: специфические для платформы виджеты – поскольку интерфейсыFlutterпишутсяспомощьюкода,увасможетбытьоднакодоваябаза,ко-тораяподдерживаеткакiOS,такиAndroid,нодажевнейестьразличия,которыевамнужноучитывать.Например,вывсегдаможетеузнатьвкодезначенияPlatform.isAndroidиPlatform.isIOS,чтобыопределить,нака-комустройствеработаетвашеприложение,азатемдобавитьусловиедлясозданияразныхвиджетовдляразныхплатформ.Возможно,вамнуженRaisedButtonнаAndroidиButtonнаiOS.
• Против:размерприложения–приложенияFlutter,какправило,немно-гобольшесвоихнативныханалогов,потомучтоонивключаютосновнойдвижокFlutter, библиотекиидругиересурсыфреймворка.Размерпри-ложенияэлементарного«Hello,world!»наFlutterможетпревышать7МБ.Поэтомуесливамрешительноваженразмерприложения,тоFlutterмо-жетстатьнелучшимвыбором.
30
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
Надеюсь,чтокэтомумоментууваспоявилосьпониманиесильныхислабыхсторонFlutter,поэтомупредлагаюперейтикпрактике.
Хватит болтать, начинаем практику с Flutter!Преждечеммыдоберемсядокода,намследуетустановитьFlutterинекото-рыеинструменты,которыемогутпонадобиться.Надеюсь,выпонимаете,чтонетакужпростоначатьписатькоднаFlutter,неустановивего!
Ксчастью,настроитьрабочееокружениедовольнолегко.
Flutter SDKПервыйшаг,которыйвыдолжнысделать,–этозагрузка,установкаинастрой-каFlutterSDK.Этооченьважно!Второйшаг,которыйтехническинеобязате-лен,нонеобходимдляцелейэтойкниги,–этозагрузка,установкаинастройкаAndroidStudio,включаяAndroidSDKиэмулятор.
Во-первых,зайдитенаhttps://flutter.ioдлязагрузкиустановочныхпа-кетовиполучениядокументацииFlutter.НажмитекнопкуGet Startedвверх-нейчасти.НайдитеInstallивыберитесвоюоперационнуюсистему(Windows,MacOSилиLinux).
Обратите внимание, что мне совсем не стыдно признать, что я в первую очередь пользователь Win-dows . Это то, в чем я разбираюсь и что предпочитаю! Так что эта книга будет ориентирована на Windows, и если вы используете другую ОС, то вы в какой-то степени будете сами по себе . С учетом вышесказан-ного я буду обращать ваше внимание на особенности инструментов для разных ОС, если будут иметь-ся существенные различия . На самом деле их не должно быть вне зависимости от того, используете вы Windows или нет . При этом Flutter сам проинструктирует вас, если возникнут проблемы .
Выберитесоответствующуюссылку,иFlutterпредоставитваминформациюозагрузкеиустановкеSDK.SDKнеотличаетсяотлюбогодругогософта,поэ-томутрудностейбытьнедолжно.Хочуотметить,чтовинструкцииваспро-сятуказатьпутьдляSDK.Новыможетепропуститьэтотшаг.Простообратитевнимание,чтоесливыпропуститеего,всекомандыдолжныбытьвыполненыизкаталогаSDK,илисуказаниемполныхпутейдоприложенийвэтомкатало-ге.КактолькомыдойдемдошагасAndroidStudio,выобнаружите,чтодобав-лениеSDKкпутидействительнонеимеетзначения,AndroidStudioсделаетэтозавас.Ноесливысобираетесьработатьскоманднойстрокой,тонезабудьтепрописатьполныйпуть.
Перваякоманда,которуювыбудетевыполнятьизкоманднойстроки,ипер-вая,которуювыбудетеделатьсразупослеустановкиSDKвсоответствиисин-струкцияминасайте,–это«flutterdoctor».Большинствокоманд,которыевыбудетевводитьприработесSDK,еслиневсеизних,начинаютсясflutter,кото-рыйфактическиявляетсяисполняемымфайлом,напримерdoctor–этоодна
31
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
изкоманд,которуювыможетевыполнитьсегопомощью.Этоважно,потомучтокомандаdoctorпроверит,сможетеливыначатьработать,иеслинет,тоскажетвам,чтонетак.
Если вы запустите ее сейчас,то, скорее всего, обнаружите проблемы,такидолжнобытьнаданномэтапе,неволнуйтесь,следующийшагэтоисправит:установкаAndroidStudio.
Android StudioЕщераз,инструкциинасайтеFlutterсопровождаютвасиимеютнезначитель-ныеразличиядлякаждойОС,нокактольковыустановилиAndroidStudio,за-пуститееёивоспользуйтесьмастеромнастройки.ЭтозагрузитAndroidSDK,образыэмулятораивсенеобходимоедляегоработы.Затемустановитеспеци-альныеплагиныDartиFlutter,вдокументацииэтоподробноописано.
Есливыпродолжитеследоватьинструкциям,запуститсяпроцессподклю-чениявашегоAndroidтелефонаилипланшетаккомпьютеру,ноубедитесь,чтоflutter doctorеговидит.Однаковыможетепропуститьэтотшаг!Конечно,еслиувасестьустройствоAndroid,тонеобходимостьвэмуляторепропадает.
ОднакоесливыпредпочитаетеiOSилиесливамненравитсяиспользоватьреальноеустройствоприразработкекодаFlutter–янеподключаюсвойте-лефон,–тогдамоепредложениесостоитвтом,чтобывойтивAndroidStudio,запуститьменеджерAVD(AndroidVirtualMachine),которыйвыможетенайтивменюконфигурациинаэкранезапускаисоздатьсебевиртуальноеустрой-ствоAndroid.ЯпредлагаюсоздатьвиртуальноеустройствоPixel_2,используяуровеньAPI28(убедитесь,чтовыустановилиданнуюверсиюAPI),изадатьемуразрешение1080×1920(420dpi)соперационнойсистемойAndroid9.За-темвыберитеобразx86 (x86_64).Еслиговоритьопроизводительности,вир-туальныеустройстваAndroidдолгоевремяимелиплохуюрепутацию,носей-часэтоттипвиртуальныхустройствработаетисключительнохорошо,дости-гаяпочтинативнойпроизводительностивбольшинствеслучаев.Хотяэтонеимеетзначения,идемдальшеинастроимегоSD-картуна512МБ.Значенияпоумолчаниюдолжнысоответствоватьвашимжеланиям,ноуровеньAPIитиппроцессора–этоключевыеаспекты.
Когдавсёбудетготово–запускаемкодFlutterнаэмуляторе.ИливыможетесделатьвсеэтоизкоманднойстрокиспомощьюSDK.МыжевданнойкнигебудемделатьэтовAndroidStudio.
Обратитевнимание,чтоесливыповторнозапуститеflutter doctor,онвсеравнобудетсообщатьопроблеме,аименночтооннеможетнайтиустройствоAndroid,предполагая,чтовиртуальноеустройство,котороевысоздали,нера-ботает.Ноесли flutterdoctorобнаружитего,онвыдаствамсправку,чтовсехорошо.Наконец,есливывидитесообщениеотом,чтоэмуляторнезапущен,приусловиичтореальноеустройствоAndroidподключеноиэтоединственнаяпроблема,окоторойсообщаетflutterdoctor,товыможетенеобращатьнанеевнимания.
32
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
ЕсливассейчасинтересуетiOS,пожалуйста,успокойтесь!Хотьмыисполь-зуемAndroidStudio,этоникоимобразомнеозначает,чтовсеэтонепримени-модляiOS.ОбiOSнеобходимознатьвпервуюочередьто,чтоесливыхоти-тепротестироватьреальноеустройствоiOSилисоздатьсвоеприложениедляпродажи,вампонадобитсякомпьютерMacиAppleXcodeIDE.Приложениядляпродажинерассматриваютсявэтойкниге,хотя,будьтодляiOSилиAndroid,эмуляторотличносоответствуетнашимзадачам.
Типичное приложение «Hello, World!»Есливыпродолжитеследоватьинструкциинавеб-сайте,топоследнимшагомстанетсозданиенебольшогоприложенияFlutter.Документациятамотличная,нояпредлагаюпропуститьееипозволитьмнепровестиваспоэтомупутиса-мому.
ПервымшагомнеобходимопозволитьAndroidStudio(всочетаниисFlutterSDK)создатьприложениедлянас.Процессдовольнопрост,икактолькомызапустимэтобазовоеприложениенанашемвиртуальномустройстве,мыне-многоизменимего,чтобывымогливидетьгорячуюперезагрузкунаглядно.
Носначаладавайтесоздадимпроект!ПрипервомзапускеAndroidStudioвыувидитеокно,какпоказанонарис.1-1.
Рисунок 1-1. Первый шаг в Android Studio
33
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
ВидитестрочкуStart a new Flutter Project?Этото,чтонужно,кликайте!Выуви-дитеначальныйэкранмастерановогоприложения,какпоказанонарис.1-2.
Рисунок 1-2. Выберите тип проекта Flutter, который хотите создать
СуществуетчетыретипапроектовFlutter,которыевыможетесоздать:
• Flutter Application(егомыбудемиспользоватьвэтойкниге);
• Flutter Plugin (плагин позволяет использовать нативнуюфункциональ-ностьAndroidилиiOSдлявашихприложенийFlutterнаосновеDart);
• Flutter Package(необходимтольковтомслучае,есливыхотитераспро-странятьпользовательскийвиджетнезависимоотприложения);
• Flutter Module(позволяетвстраиватьприложениеFlutterвнативноепри-ложениеAndroid).
ВыберитеFlutter Application и нажмите кнопкуNext (Далее). Откроетсяокно,какпоказанонарис.1-3.
34
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
Рисунок 1-3. Ввод необходимой информации о вашем приложении
Здесьвывведетеинформациюосоздаваемомприложении.Выможетедатьпроектулюбоеназваниеилиописание,атакжеоставитьзначенияпоумолча-нию.ПринеобходимостиобновитеполеProject location(илипростоисполь-зуйтезначениепоумолчанию).Вывидитеэтуошибкувнизу?Непугайтесь,выужевыбралинужныйпуть.Ноесливывидитеэто,тоAndroidStudioещенезнает,гденаходитсяFlutterSDK,ивамнеобходимоегоуказать.Простопе-рейдитекSDK,которыйвыдолжныбылиустановитьранее,иубедитесь,чтоAndroidStudioэтимдоволен(ошибкаисчезнет),иснованажмитекнопкуNext,чтобыперейтикэкранусрис.1-4.
35
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
Рисунок 1-4. Окончательная информация о проекте
Этотэкрантребуетнемногобольшеинформации,впервуюочередьдоменкомпании.Еслиуваснетдомена,товыможетепоместитьлюбоезначение,ко-тороевамнравится.ТебязовутJim?Тыможешьввести«Jim»!Тыможешьна-писать«Jim»,дажееслиэтонетвоеимя,хотяэтобылобынемногостранно.Обратитевнимание,чтополноеимяпакетасостоитизназванияприложенияидоменавашейкомпании,введенногонапоследнемэкране.Этоимяпакетадолжнобытьуникальным,есливыхотитеопубликоватьприложениевмага-зинеприложений,хотядлянашеготестированияздесьэтонеимеетзначения.
Примечание. Вы также можете увидеть поле Sample Application, в зависимости от версии Android Studio и установленного плагина Flutter . Это для того, чтобы мастер сгенерировал образец кода для вас, если хотите, но нам это не нужно .
Наконец, выберите язык платформы, оставляя Kotlin неотмеченным, таккакSwiftбудетнаиболееподходящим.Этоотноситсякбазовомуязыкуплат-формы,используемомуподоберткамиFlutter,иесливынесобираетесьвзаи-
36
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
модействоватьснативнымкодомприложения,вам,поидее,должнобытьбезразницы.Вконечномсчетеэтонеимеетзначениядляцелейкниги.
ТакчтонажмитекнопкуFinish,иAndroidStudioпокажетвампростоепри-ложениеFlutter.Этоможетзанятьнесколькоминут,поэтомупроверьтестро-кусостояниявнизу,чтобыубедиться,чтовсезадачивыполнены.Когдавсёбу-детготово,посмотритевверхнюючастьAndroidStudio,напанельинструмен-тов,инайдитевыпадающийэлемент,вкоторомперечисленыподключенныеустройства,какпоказанонарис.1-5.
Рисунок 1-5. Выпадающий список устройств в Android Studio
Выдолжны увидеть созданныйранее эмулятор. Выберите его, и, если онещенезапущен,ондолжензапуститьсявближайшеевремя.Кактолькоэтопроизойдет,нажмитеназначокRun(зеленуюстрелкурядомсвыпадающимспискомmain.dart)–этоточказапускаприложения.Подождите,покаприло-жениебудетсобрано,развернутоизапущенонаэмуляторе(взависимостиотвашеймашиныэтоможетзанятьдоминуты,поэтомубудьтетерпеливы–про-цессускоритсяпослепервойсборки).Выдолжныувидетьвэмуляторечто-товродерис.1-6.
37
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
Рисунок 1-6. Мое первое приложение Flutter!
Этопростоеприложение,ноономногоепоказывает.Нажмитенакруглуюкнопку со знаком «плюс» (она называется «плавающей кнопкой действия»,илиFloatingActionButton,FAB)иобратитевнимание,чтосчетчикувеличива-етсяскаждымщелчкоммыши.
Получившийся код должен автоматически открываться в Android Studio(еслифайлmain.dartнайденвдиректорииверхнегоуровня)ибытьследую-щим(я,конечно,удалилкомментариииотформатировалего,чтобыонлучшевыгляделвпечатномварианте):
import‘package:flutter/material.dart’;
voidmain()=>runApp(MyApp());
classMyAppextendsStatelessWidget{
@override Widgetbuild(BuildContextcontext){ return MaterialApp( title:‘FlutterDemo’, theme:ThemeData( primarySwatch:Colors.blue,
38
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ ), home:MyHomePage(title:‘FlutterDemoHomePage’), ); } }
classMyHomePageextendsStatefulWidget{
MyHomePage({Keykey,this.title}):super(key:key);
finalStringtitle;
@override _MyHomePageStatecreateState()=>_MyHomePageState(); }
class_MyHomePageStateextendsState<MyHomePage>{
int_counter=0;
void_incrementCounter(){ setState((){ _counter++; }); }
@override Widgetbuild(BuildContextcontext){ return Scaffold( appBar: AppBar( title:Text(widget.title), ), body:Center( child:Column( mainAxisAlignment:MainAxisAlignment.center, children:<Widget>[ Text( ‘Youhavepushedthebuttonthismanytimes:’, ), Text( ‘$_counter’, style:Theme.of(context).textTheme.display1, ), ], ), ), floatingActionButton:FloatingActionButton( onPressed:_incrementCounter, tooltip:‘Increment’,
39
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ child:Icon(Icons.add), ), ); }}
Хотяздесьнетакмногокода,затоонмногоделает.Думаю,покавамнедо-статочнознаний,чтобыполностьюразобратьсявпроисходящем,ведьмыещенеговорилиоDartнастолькоподробно.Ноянехочуоставлятьвасабсолютновневедении,такчтоестьнесколькоключевыхмоментов,которыеяразъясню.
Во-первых,обратитевнимание,чтоосновнаяточкавходакаждогоприложе-нияFlutterявляетсяметодомmain().Вmain()вызываетсяметодrunApp(),кото-рыйвозвращаетвиджетверхнегоуровня.Вначалеиерархиивсегдаестьвиджет,которыйсодержитвсеостальные,здесьэтоэкземплярклассаMyApp.Этотклассявляетсявиджетомбезсостояния,поэтомуединственнаяегозадача–предоста-витьметодbuild().Виджет,возвращаемыйизнего(помните:build()–всегдавозвращающийвиджет,вкотороммогутбытьдочерниеэлементы,амогутинебыть), – это экземпляр MaterialApp, который является виджетом, предостав-леннымFlutter (этоможноувидетьв самомначаленашегокода).Мыпогово-римобэтомвиджетевглаве3,когдабудемподробнеерассматриватьвиджетыFlutter,ноглавное,чтоонобеспечиваетбазовуюинфраструктурудляприложе-нияMaterial.Каквидите,мызадалиназваниеводномизаргументовконструк-тораMaterialApp,этоназваниевыувидитевстрокесостояния(StatusBar)вашегоприложения.ТакжевыможетеустановитьтемудляприложенияFlutterипредо-ставитьподробнуюинформациюоней,напримеросновнойцвет,которыйонаиспользует,унасонсиний.
НашвиджетMaterialAppсодержитодиндочернийэлемент,которыйпред-ставленэкземпляромклассаMyHomePage.
КлассMyHomePageопределяетвиджетссостоянием,такчтонампонадобитсядвакласса,класс«core»,которыйнаследуетсяотStatefulWidget,икласссосто-яния,связанныйсним,наследуетсяотState.
Влюбомслучае,методbuild()этоговиджетасновавозвращаетединствен-ныйвиджет,наэтотразScaffold.Нонезацикливайтесьнаэтом,потомучтовглаве3мыразберемкаждыйизних.Есливдвухсловах,тоScaffoldобеспе-чиваетфундаментальныйвизуальныймакетдляприложения,включаятакиеэлементы,какстрокасостояния(AppBar–этофактическивиджет),гденахо-дитсяназвание.Scaffoldтакжеобеспечиваетмеханизмы,позволяющие«за-цепить» FAB, – экземпляр виджета FloatingActionButton передается в кон-структорScaffold.
Другойаргумент,переданныйвконструкторScaffold,–этотело,вкотороемыдобавляемдругиевиджетывкачестведочерних.Здесьвыможетенаблю-датьмантру«всеэтовиджет»вдействии,потомучтоунасестьцентральныйвиджет,которыйявляетсяконтейнернымвиджетом,который–каквыужедо-гадались–центрирует свойдочернийэлемент.В этомслучаедочернимяв-ляется виджетColumn, которыйразмещает уже своихдетей в одну колонну.
40
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
Column содержитдвадочернихвиджетаText–одиндлястатическоготекста«Youhavepushedthebuttonthismanytimes:»,адругойдляотображенияколи-честванажатийкнопки.
Все станетпонятнее, когдамывтечение следующихдвух глав углубимсявDart,азатемвоFlutter.Ихотяяопустилмногодеталей,мнекажется,этогообъяснениявполнедостаточнодлядостойногопредставленияотом,чтопро-исходитвкоде.
Горячая перезагрузка: вот что я люблю!Здесьвсестановитсяневероятнокрутым!Убедитесь,чтоувасестьприложе-ние,работающеевэмуляторе,азатемперейдитекAndroidStudioинайдитеэтустрокукода:
Text( ‘Youhavepushedthebuttonthismanytimes:’,),
Итак,выможетеизменитьданныйтекст,поменяв«button»на«FAB»иза-жавCtrl+S,иливыберитеSave AllвменюFile.Теперьнаблюдайтезаэмулято-ром,ипочтисразувыувидите,чтовашеизменениеотражаетсянаэкране(этоможетзанятьнесколькосекунд,новсёжебыстрее,чемприпервомзапуске).
Оченькруто,неправдали?Горячаяперезагрузкаработаеттольковрежимеотладки,вкоторомвына-
ходитесь;этоможнопонятьблагодаряотладочномубаннерувправомверх-немуглуприложения.Вэтомрежимевашеприложениефактическиработа-етввиртуальноймашинеDart (VM), анекомпилируетсяв собственныйкодпроцессора,чтопроисходит,когдавысоздаетереальноеприложение(да,вашеприложениебудетработатьмедленнееврежимеотладки).Горячаяперезагруз-каработаетпутемобновленияизмененныхфайловисходногокодавужера-ботающуювиртуальнуюмашинуDart,накоторойразмещаетсявашеприложе-ние.Когдаэтопроисходит,VMобновляетклассы,которыеизменились,обнов-ляялюбыеизмененныеполяиметоды.ЗатемструктураFlutterинициируетперестроениедеревавиджетов,ивашиизмененияотражаютсяавтоматиче-ски.Вамненужнопересобиратьилиперезапускатьчто-либо;всепроисходитавтоматическипомеренеобходимости,чтобывашиизменениябылиотобра-женынаэкранекакможнобыстрее.
Времяотвременивыможетеобнаружить,чтоизменениенеприводиткпе-резагрузке,какожидалось.Еслиэтопроизойдет,первое,чтонужнопопробо-вать,–этонажатьназначокгорячейперезагрузкинапанелиинструментов,которыйнарис.1-7выглядиткакмолния(вытакжеможетенайтиопциюго-рячейперезагрузкивменюRunссоответствующейгорячейклавишейCtrl+/).
41
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
Рисунок 1-7. Значок горячей перезагрузки в Android Studio
Это должно помочь вам. Также обратите внимание на консоль, котораядолжнанаходитьсявнижнейчастиAndroidStudio,тамвыувидитеследующеесообщение:Performing hot reload...Reloaded1of448librariesin2,777ms.
Крометого,небольшаяподсказкадолжнапоявитьсярядомсконсольювовремяперезагрузки.
Обратитевнимание,есливынажалинаFABнесколькораз,азатемизмени-литекст,текущеесостояниеприложенияпродолжитсуществование.Другимисловами,количествоповторныхнажатийнакнопкусохранитсяпослегорячейперезагрузки(hotreload).Этопозволяетлегкоизменятьпользовательскийин-терфейсимгновенноотображатьтекущеесостояние,такчтовыможетебы-строипростосверятьвашуверсткусдизайном.Ночто,есливыхотите,чтобысостояниенесохранялось?Тогдавы,вероятно,захотитевыполнитьгорячийперезапуск(restart).Поэтомувамследуетсделатьэтовручную(вотличиеотгорячейперезагрузки,котораяпроисходитавтоматически,когдавывноситеизменениявкодисохраняетеего),выбравопциюHot restart(горячийпереза-пуск–неперезагрузка)вменюRunилинажавсоответствующуюгорячуюкла-вишу(Ctrl+Shift+/).
Интересно,чтозначкадлягорячегоперезапусканапанелиинструментовнет,ноэтовсёжеперезапуститвашеприложение,хотьиневыполнитновуюсборкуиочисткусостояния.
Вы,естественно,можетеперезапускатьсборкувлюбоевремя(этопроисхо-дитпокомандеRun),нокаждыйразвыбудетедожидатьсякомпиляции,чтоникапелькинеэкономитвашевремя.Горячийперезапуск(restart)сработаетпочтитакжебыстро,какигорячаяперезагрузка(reload),потомучтоработыонделаетнамногоменьше,нодостигаетпримернотогожеэффекта.
Надеюсь,вывидите,наскольковыможетебытьэффективны,используягоря-чуюперезагрузку.Мнекажется,выоценитеэто,когдапознакомитесьсFlutterпоближе!
42
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
Базовая структура приложения FlutterОднаизпоследнихтем,которойякоснусьвовступительнойглаве,–этообщаяструктураприложения,котороебылосозданодлявас.Нарис.1-8вывидитепервичнуюструктурукаталога.
Рисунок 1-8. Первичная структtура каталога проекта
43
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
Каквидите,существуетпятькаталоговверхнегоуровня.Атеперьподроб-нееокаждомизних:
• android–содержитспецифическийдляAndroidкодиресурсы,такиекакзначки приложений, код Java, а также конфигурациюGradle и ресурсы(GradleявляетсясистемойсборкиAndroid).Насамомделеэтофактиче-скицелыйпроектAndroid,которыйвыможетепостроитьсиспользова-ниемстандартныхинструментовAndroid.Побольшомусчету,вамнуж-ноизменятьтолькозначки(которыенаходятсявкаталогахandroid/app/src/main/res,гдекаждыйподкаталогимеетразноеразрешение)и,вза-висимостиоттого,чтоделаетвашеприложение,файлAndroidManifest.xmlвandroid/app/src/main,гдевыможетеустановитьспециальныесвой-стваприложениядляAndroid;
• ios – как и android, этот каталог содержит код проекта, специфичныйдля iOS. Критическим содержимым здесь является каталог ios/Runner/Assets.xcassets, в котором находятся значки для вашего приложения,ифайлInfo.plistвios/Runner,которыйслужиттойжецели,чтоифайлAndroidManifest.xmlдляприложенийAndroid;
• lib–хотясначалаэтоможетпоказатьсястранным,этоместо, гдебудетжитьвашкод!Выможетеотносительносвободноорганизовыватьсвойкод,создаваялюбуюструктурукаталогов,хотявампонадобитсяодинфайл,ко-торыйслужитточкойвхода,ибольшуючастьвремениимбудетmain.dart,созданныйавтоматически;
• res–этоткаталогсодержиттакиересурсы,какстрокидляпереводаваше-гоприложениянаиностранныеязыки.Новэтойкнигемынебудемиметьснимидело;
• test–здесьвынайдетеDart-файлыдлятестированиявашегоприложе-ния.FlutterпредоставляетутилитуWidgetTester,котораяиспользуетав-томатическиетесты,чтобыподтвердитьфункциональностьвашихвид-жетов.Мынебудемснимработать,такжекакисres,потомучтоэтонео-бязательнаячастьразработкиFlutter,окоторойотдельноможнонаписатьцелуюкнигу!Тестирование–это,конечно,важно,нопокавыненаучи-тесьписатьприложенияFlutter,вамбудетнечеготестировать,аэтакнигафокусируетсянапервойчастивашегопути.
Хотьони скрытпоумолчаниювAndroidStudio, естьтакжекаталог.idea,вкоторомхранитсяинформацияоконфигурацииAndroidStudio,поэтомувыможетеегоигнорировать(обратитевнимание,чтоAndroidStudioосновананаIDEIntelliJIDEA,отсюдаиназвание).Существуеттакжескрытыйкаталогсбор-ки, содержащий информацию, которуюиспользуютAndroid Studio и FlutterSDKдлясозданиявашегоприложения.Номыпроигнорируемиэто.
Помимо каталогов, вытакже найдете некоторыефайлы в корне проекта.Это,какправило,единственныефайлы,окоторыхвамнужнобеспокоитьсяза
44
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
пределамикаталогаlib(всеостальноенаскриншотевамненужнознатьвооб-ще),иэто:
• .gitignore–файлуправленияверсиямиGitиспользуется,чтобызнать,ка-киефайлыигнорироватьизуправленияверсиями.ИспользованиеGitсо-вершеннонеобязательнопринаписанииприложенийFlutter,ноэтотфайлгенерируетсявлюбомслучае.Управлениеверсиями–этото,чтонесмо-жетохватитьдажецелаякнига,поэтомувыможетеигнорироватьданныйфайл;
• .metadata–данные,которыеAndroidStudioотслеживаетввашемпроек-те.Выможетеигнорироватьиэто,таккаквыникогданебудетередакти-роватьихсамостоятельно;
• .packages–уFlutterестьсвойсобственныйменеджерпакетовдляуправ-ления зависимостями в вашем проекте. Этот менеджер пакетов назы-ваетсяPub,иониспользуетсядляотслеживаниязависимостейввашемпроекте.Вынебудетевзаимодействоватьсниминапрямуюилидажена-прямуюсPub,поэтомуеготожеможнооставитьбезвнимания;
• *.iml–этотфайлдолженбытьназванвчестьвашегопроектаиявляетсяфайломконфигурациипроектаAndroidStudio.Выникогданебудетере-дактироватьегонапрямую,такчтоигнорируем;
• pubspec.lockиpubspec.yaml–выкогда-нибудьработалисNPM?Знако-мы с package.json ифайлами package-lock.json, которые он использует?Ну,этотежевещи,нодляPub!ЕсливынезнакомысNPM,pubspec.yaml–этото,каквыописываетесвойпроектдляPub,включаяегозависимости.Файлpubspec.lock–этовнутреннийфайлPub.Выопределенноможетередактироватьpubspec.yaml,нонеpubspec.lock,аpubspec.yamlмыпозжеподробнорассмотрим;
• README.md–файлreadme,которыйвыможетеиспользовать,какхотите.Какправило,этофайлMarkdown–сайты,такиекакGitHub,используютдляотображенияинформацииовашемпроектеприпереходекрепози-торию,гдеэтотфайлнаходитсявкорневомкаталоге.
Самымважнымфайломздесьявляетсяpubspec.yaml,ионодинизнемно-гих,которыевамнужнобудетредактировать,поэтом,есливывсезабыли,еголучшезапомните!Мыдоберемсядонегопозже,когданамнужнобудетдоба-витьзависимостивнашпроект,нонаданныймоментсгенерированногофай-лавполнедостаточнодлянашихнужд.
Еще парочка моментов «под прикрытием»Есливыпосмотритенанекоторыеизфайловвкаталогеios,тозаметитесло-во«Runner».Этоподсказкаотом,какработаютприложенияFlutterприсбор-кеизапускеустановочногопакета.Какотмечалосьранее,горячаяперезагруз-
45
ГЛАВА 1 . FLUTTER: ПЛАВНОЕ ПОГРУЖЕНИЕ
каработает,потомучтоврежимеотладкивашкодзапускаетсяввиртуальноймашине.Однакоприсборкеустановочногопакетаэтотакнеработает.ВашкодкомпилируетсявсобственныйкодARM.Фактическикомпилируетсявбибли-отекудляпроцессораARM,которуювдальнейшемиспользуетнативноепри-ложение,этообъясняет,почемувашкоднаходитсявкаталогеlib.
БиблиотекиFlutterнарядусвашимкодомприложениякомпилируются«дозапуска» (Ahead-Of-Time, AOT) с помощью LLVM (Low-Level Virtual Machine,инфраструктуракомпилятора,написаннаянаC++,котораяпредназначенадлякомпиляциииоптимизациипрограмм,написанныхнаразличныхязыкахпро-граммирования)наiOS.НаAndroidиспользуетсяNativeDevelopmentKit(NDK)для сборки ARM-библиотеки. Эта библиотека включена в так называемый«runner»,которыйявляетсяпростонативнымприложением,которое...подо-ждите,подождите...запускаетвашеприложение.Представьте,чтоэтотонкаяоберткавокругвашегоприложения,котораязнает,какзапуститьприложение,ипредоставляетнеобходимыеусловия.Внекоторомсмыслеrunnerпо-преж-немупредставленвиртуальноймашиной,хотяиоченьтонкой(почтикаккон-тейнерDocker,есливыснимзнакомы).
Наконец,runnerвместесоскомпилированнойбиблиотекойупаковываетсявфайл.ipaдля iOSилифайл.apkдляAndroid,иувасестьполный,готовыйкустановкеилипубликациипакет!Когдаприложениезапускается,runnerза-гружаетбиблиотекуFlutterивашкодприложения,исэтогомоментавсявизу-ализация,ввод/выводиобработкасобытийделегируетсяскомпилированномуприложениюFlutter.
ПРИМЕЧАНИЕ. Это очень похоже на то, как работает большинство кроссплатформенных мобильных игровых движков . Ранее я написал книгу о Corona SDK, библиотеке, которую я очень люблю, она работает очень похожим образом, хотя там используется язык Lua вместо Dart (который, могу поспорить, команда Flutter тоже рассматривала!) . Любопытно, что Google, по сути, черпал вдохновение из игровых движков, чтобы создать Flutter, потому что это доказывает то, что я всегда говорил: если вы хотите быть лучшим программистом, единственный вид проекта, в котором вам следует отточить свои навыки, – это игровой . На этот раз мир получил целую платформу приложений! И если вы еще не заглянули вперед, последние две главы этой книги посвящены созданию игры Flutter, потому что я всегда советую создавать игры!
ИтогоСэтойглавойвыначалисвоепутешествиевмирFlutter!Выузналиотом,чтотакоеFlutter,чтоонпредлагаетипочемувамстоитегоиспользовать(идаженекоторыепричины,покоторымвынезахотитеегоиспользовать).Выузналиоважныхконцепциях,такихкакDartивиджеты;узнали,какнастроитьсвоюсредуразработки,чтобыработатьскодомFlutter;создалисвоепервоеоченьпростоеприложениеFlutterизапустилиеговэмуляторе.
ВследующейглавевыпоближепознакомитесьсDartиполучитехорошуюбазу,чтобыприступитьксозданиюреальныхприложенийFlutter!