The words you are searching are inside this book. To get more targeted content, please make full-text search by clicking here.

Книга посвящена практическому применению фреймворка Flutter и языка программирования Dart. Показан синтаксис Dart, описаны основные структуры языка. Раскрыты принципы создания мобильных и настольных приложений с использованием Flutter для операционных систем Android, iOS, Linux, macOS, Windows и Google Fuchsia. Рассказано о работе с данными и виджетами, об использовании различных решений облачных провайдеров и интегрирации их с приложениями на Flutter. Рассмотрено управление данными через API с помощью Google Cloud. Представлены приемы работы с решениями Firebase, такими как аутентификация и база данных Cloud Firestore.

Discover the best professional documents and content resources in AnyFlip Document Base.
Search
Published by BHV.RU Publishing House, 2024-06-16 11:09:39

Flutter и Dart. Сборник рецептов: Разработка полнофункциональных облачных приложений

Книга посвящена практическому применению фреймворка Flutter и языка программирования Dart. Показан синтаксис Dart, описаны основные структуры языка. Раскрыты принципы создания мобильных и настольных приложений с использованием Flutter для операционных систем Android, iOS, Linux, macOS, Windows и Google Fuchsia. Рассказано о работе с данными и виджетами, об использовании различных решений облачных провайдеров и интегрирации их с приложениями на Flutter. Рассмотрено управление данными через API с помощью Google Cloud. Представлены приемы работы с решениями Firebase, такими как аутентификация и база данных Cloud Firestore.

Ричард Роуз Астана «АЛИСТ» 2024


УДК 004.438 ББК 32.973.26-018.2 Р79 Роуз Р. Р79 Flutter и Dart. Сборник рецептов: Пер. с англ. — Астана: АЛИСТ, 2024. — 272 с.: ил. ISBN 978-601-09-5052-8 Книга посвящена практическому применению фреймворка Flutter и языка программирования Dart. Показан синтаксис Dart, описаны основные структуры языка. Раскрыты принципы создания мобильных и настольных приложений с использованием Flutter для операционных систем Android, iOS, Linux, macOS, Windows и Google Fuchsia. Рассказано о работе с данными и виджетами, об использовании различных решений облачных провайдеров и интеграции их с приложениями на Flutter. Рассмотрено управление данными через API с помощью Google Cloud. Представлены приемы работы с решениями Firebase, такими как аутентификация и база данных Cloud Firestore. Для программистов УДК 004.438 ББК 32.973.26-018.2 © 2024 ALIST LLP Authorized Russian translation of the English edition of Flutter and Dart Cookbook ISBN 9781098119515 © 2023 Richard Rose. This translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls all rights to publish and sell the same. Авторизованный перевод с английского языка на русский издания Flutter and Dart Cookbook ISBN 9781098119515 © 2023 Richard Rose. Перевод опубликован и продается с разрешения компании-правообладателя O’Reilly Media, Inc. ISBN 978-1-098-11951-5 (англ.) ISBN 978-601-09-5052-8 (каз.) © Richard Rose, 2023 © Издание на русском языке. ТОО "АЛИСТ", 2024


Оглавление Вступительное слово ....................................................................................................... 9 Предисловие ................................................................................................................... 10 Кто должен прочитать эту книгу.................................................................................................. 10 Почему я написал эту книгу ......................................................................................................... 11 Как организована эта книга .......................................................................................................... 11 Соглашения об используемых обозначениях.............................................................................. 12 Онлайн-обучение O’Reilly ............................................................................................................ 12 Наши контакты .............................................................................................................................. 12 Благодарности ................................................................................................................................ 13 Глава 1. Переменные Dart ........................................................................................... 14 1.1. Выполнение приложения Dart ............................................................................................... 14 1.2. Работа с целыми числами ...................................................................................................... 15 1.3. Работа с дробными числами .................................................................................................. 17 1.4. Работа с логическими значениями ........................................................................................ 17 1.5. Работа со строками ................................................................................................................. 18 1.6. Вывод информации на консоль ............................................................................................. 19 1.7. Работа с постоянной переменной (на этапе компиляциии) ................................................ 20 1.8. Работа с постоянной переменной (на этапе выполнения) ................................................... 20 1.9. Работа с null-значениями ....................................................................................................... 21 Глава 2. Управление потоком ..................................................................................... 23 2.1. Проверка выполнения условия .............................................................................................. 23 2.2. Неопределенная итерация ...................................................................................................... 24 2.3. Перебор набора элементов..................................................................................................... 26 2.4. Выполнение условных действий, основанных на значении ............................................... 27 2.5. Использование перечислений ................................................................................................ 29 2.6. Реализация обработки исключений ...................................................................................... 30 Глава 3. Использование функций .............................................................................. 32 3.1. Объявление функций .............................................................................................................. 32 3.2. Добавление параметров ......................................................................................................... 33 3.3. Использование необязательных параметров ........................................................................ 34 3.4. Возвращаемые значения ........................................................................................................ 35 3.5. Объявление анонимных функций ......................................................................................... 36 3.6. Добавление функциональной задержки с помощью класса Future ................................... 37 Глава 4. Структуры List и Map ................................................................................... 39 4.1. Создание списков данных List ............................................................................................... 39 4.2. Внесение изменений в список ............................................................................................... 41


6 | Оглавление 4.3. Использование в списке данных разных типов ................................................................... 42 4.4. Работа с парами "ключ/значение" в структуре Map ............................................................ 43 4.5. Вывод данных из структуры Map ......................................................................................... 45 4.6. Проверка наличия содержимого в структуре Map .............................................................. 46 4.7. Вывод сложных типов данных .............................................................................................. 46 Глава 5. Объектно-ориентированный Dart .............................................................. 48 5.1. Введение в объектно-ориентированный Dart ....................................................................... 48 5.2. Создание класса ...................................................................................................................... 49 5.3. Инициализация класса с помощью конструктора ............................................................... 51 5.4. Наследование классов ............................................................................................................ 52 5.5. Интерфейс класса ................................................................................................................... 54 5.6. Класс Mixin .............................................................................................................................. 57 Глава 6. Тестирование приложений Dart ................................................................. 60 6.1. Добавление тестирующего пакета к вашему приложению ................................................. 61 6.2. Создание пробного теста приложения .................................................................................. 62 6.3. Выполнение тестов в вашем приложении ............................................................................ 63 6.4. Группировка нескольких тестов ............................................................................................ 65 6.5. Добавление фиктивных тестовых данных ............................................................................ 68 Глава 7. Знакомство со средой разработки Flutter ................................................. 70 7.1. Макетирование интерфейса приложения ............................................................................. 70 7.2. Создание шаблонного проекта Flutter................................................................................... 72 7.3. Удаление баннера отладки Flutter ......................................................................................... 74 7.4. Знакомство с виджетами ........................................................................................................ 75 7.5. Дерево виджетов Flutter ......................................................................................................... 76 7.6. Улучшение производительности рендеринга виджета ....................................................... 77 Глава 8. Ассеты .............................................................................................................. 79 8.1. Использование файла pubspec.yaml ...................................................................................... 79 8.2. Добавление папки ассетов ..................................................................................................... 81 8.3. Ссылка на изображение ......................................................................................................... 82 8.4. Встраивание пакета шрифтов Google ................................................................................... 83 8.5. Импорт пакета ......................................................................................................................... 84 Глава 9. Работа с виджетами ....................................................................................... 86 9.1. Создание виджета без сохранения состояния ...................................................................... 86 9.2. Создание виджета с сохранением состояния ....................................................................... 88 9.3. Рефакторинг виджетов Flutter ............................................................................................... 91 9.4. Использование класса Scaffold .............................................................................................. 94 9.5. Добавление панели приложения AppBar .............................................................................. 96 9.6. Использование контейнера .................................................................................................... 98 9.7. Центрированный виджет ..................................................................................................... 101 9.8. Виджет SizedBox ................................................................................................................... 102 9.9. Виджет Column ..................................................................................................................... 105 9.10. Виджет Row ......................................................................................................................... 109 9.11. Виджет Expanded ................................................................................................................ 111 Глава 10. Разработка интерфейсов пользователей ............................................... 114 10.1. Использование пакета шрифтов Google ........................................................................... 114 10.2. Встраивание виджета RichText .......................................................................................... 116


Оглавление | 7 10.3. Идентификация хост-платформы ...................................................................................... 117 10.4. Использование виджета Placeholder ................................................................................. 119 10.5. Использование виджета LayoutBuilder ............................................................................. 121 10.6. Доступ к размерам экрана с помощью MediaQuery ........................................................ 125 Глава 11. Организация данных на экране .............................................................. 128 11.1. Реализация вертикального списка ListView ...................................................................... 129 11.2. Реализация горизонтального списка ListView .................................................................. 131 11.3. Виджет SliverAppBar .......................................................................................................... 134 11.4. Виджет SliverList ................................................................................................................. 136 11.5. Виджет GridView................................................................................................................. 140 11.6. Виджет SnackBar (всплывающих уведомлений) ............................................................. 143 Глава 12. Межстраничная навигация Flutter ........................................................ 146 12.1. Добавление императивной межстраничной навигации .................................................. 146 12.2. Добавление декларативной межстраничной навигации ................................................. 150 12.3. Использование выдвижной панели навигации Navigation Drawer ................................ 154 12.4. Работа с вкладками ............................................................................................................. 158 12.5. Добавление нижней навигационной панели .................................................................... 162 12.6. Использование ключей для передачи информации ......................................................... 164 Глава 13. Работа с ассетами данных ........................................................................ 167 13.1. Стратегический подход к получению данных ................................................................. 168 13.2. Рефакторинг данных .......................................................................................................... 169 13.3. Генерация классов Dart из структур JSON ....................................................................... 171 13.4. Асинхронное использование локальных данных JSON .................................................. 174 13.5. Использование набора данных JSON из папки ассетов .................................................. 178 13.6. Доступ к удаленным данным JSON .................................................................................. 181 Глава 14. Тестирование пользовательского интерфейса с помощью Flutter ........................................................................................................ 184 14.1. Автоматизированное тестирование виджетов Flutter ...................................................... 184 14.2. Автоматизированное тестирование виджетов ................................................................. 187 14.3. Интеграционное тестирование с помощью Flutter Driver ............................................... 188 14.4. Тестирование совместимости с устройствами на Android/iOS....................................... 189 Глава 15. Firebase и Flutter ........................................................................................ 192 15.1. Использование платформы Firebase совместно с Flutter ................................................. 192 15.2. Настройка проекта Firebase ............................................................................................... 194 15.3. Настройка Firebase SDK для локальной разработки ....................................................... 196 15.4. Конфигурация эмуляторов Firebase .................................................................................. 198 15.5. Добавление в среду разработки пакета flutterfire_cli ...................................................... 200 15.6. Интеграция с базой данных Firebase ................................................................................. 202 15.7. Запись в облачную базу данных Firestore ......................................................................... 205 15.8. Чтение из облачной базы данных Firestore ...................................................................... 209 15.9. Добавление аутентификации Firebase в приложение Flutter .......................................... 214 15.10. Использование веб-приложения Flutter с Firebase Hosting ........................................... 219 Глава 16. Введение в облачные сервисы ................................................................ 221 16.1. Начало работы с провайдерами облачных сервисов ....................................................... 221 16.2. Работа с идентификационными данными и управлением доступом ............................. 222


8 | Оглавление 16.3. Использование облачного хранилища для размещения объекта ................................... 224 16.4. Разработка HTTP-сервера с помощью Dart ...................................................................... 225 16.5. Создание контейнера Dart .................................................................................................. 227 16.6. Внедрение бессерверности с помощью Dart .................................................................... 228 Глава 17. Начинаем разработку игр ........................................................................ 230 17.1. Добавление пакета Flame к Flutter .................................................................................... 231 17.2. Создание шаблона Flame ................................................................................................... 232 17.3. Добавление спрайта ............................................................................................................ 233 17.4. Добавление к спрайту ручного горизонтального перемещения ..................................... 235 17.5. Добавление автоматического вертикального перемещения спрайта ............................. 238 17.6. Добавление обнаружения столкновений .......................................................................... 241 17.7. Добавление рендеринга текста .......................................................................................... 244 17.8. Добавление графических примитивов .............................................................................. 248 17.9. Добавление звуковых эффектов ........................................................................................ 253 Приложение. Настройка среды разработки ........................................................... 260 Определение варианта установки Dart ...................................................................................... 260 Использование DartPad ............................................................................................................... 261 Установка среды разработки Flutter ........................................................................................... 262 Использование Flutter Doctor ...................................................................................................... 262 Установка Dart SDK .................................................................................................................... 264 Разработка с использованием VS Code...................................................................................... 264 Расширение Android Studio для поддержки Dart ...................................................................... 265 Выбор канала выпуска ................................................................................................................ 265 Использование конфигуратора Flutter для установки целевой платформы ........................... 266 Предметный указатель ............................................................................................... 268 Об авторе ....................................................................................................................... 271 Об изображении на обложке ...................................................................................... 271


Вступительное слово Ежедневно я встречаю людей, создающих удивительные приложения и отличный контент с помощью Flutter и Dart. Как Flutter, так и Dart помогают разработчикам быстрее научиться реализовывать свои идеи. Когда Ричард Роуз сообщил мне, что он пишет эту книгу, я понял, что она поможет тысячам программистов. Стиль книги рецептов и подход к проблеме с точки зрения анализа примеров — это привлекательный путь к освоению Flutter и Dart. Рич, как один из пионеровпользователей Flutter и Dart, делает огромную работу по распространению ценных приемов и рекомендаций. Книга является отличным настольным справочником, в котором вы найдете ответы на многие вопросы, возникающие в повседневной работе. Я рад рекомендовать эту книгу и надеюсь, что она поможет вам раскрыть потенциал фантастического опыта создания Flutter-приложений и работы с языком Dart. – Маджид Хаджян Разработчик-эксперт по Flutter и Dart, Руководитель отдела по связям с разработчиками Осло, ноябрь 2022


Предисловие Добро пожаловать в Flutter и Dart. Книга рецептов. Flutter — этомультиплатформенный фреймворк, который сейчас очень популярен в среде разработчиков. Dart представляет собой богатый набор средств разработки (SDK), лежащий в основе Flutter. Вместо того чтобы изучать множество технологий, с помощью Flutter вы сможете разрабатывать код, полноценно работающий одновременно на платформах Android, iOS, Linux, Windows и в веб-приложениях. Как человека, проводящего много времени в YouTube, меня всегда глубоко впечатляли примеры красивых приложений. Dart и Flutter стали инструментами, которые заставили меня не только снова полюбить программирование, но и позволили мне познакомиться с потрясающими людьми. Flutter-сообщество сейчас находится на подъеме и продолжает поставлять инновационный высококачественный контент как в YouTube, так и сообществу разработчиков Google, посвящая свой опыт и время людям, которые намерены закрепиться в индустрии информационных технологий. Независимо от того, являетесь ли вы опытным разработчиком или начинающим, работа с Flutter станет для вас удовольствием. Flutter можно освоить очень быстро, однако это мощное средство, позволяющее интегрироваться в такие сильные облачные решения, как Firebase. Начните сегодня и создайте приложение для миллионов пользователей. Кто должен прочитать эту книгу Знакомы ли вы с Flutter и Dart или нет, вы человек, чувствующий непреодолимый призыв к созиданию. Не обращайте внимания на желание оставить это "на потом" — начинайте строить будущее сейчас. Но как поддерживать мотивацию и достичь момента, когда вы почувствуете способность создать достойное приложение? Читайте эту книгу. Прелесть изучения Flutter и Dart в том, что они имеют очень низкий "входной порог". Разработка приложения требует как опыта, так и определенных усилий, и это причина, по которой программистам хорошо платят. Неважно, есть ли у вас навыки в нескольких языках программирования или вы имеете нулевой опыт в разработке, Flutter и Dart — это отличная отправная точка к созданию потрясающих программ. С первого дня вы получите перспективу стать автором очень красивых приложений.


Предисловие | 11 Создание приложений — это механизм с множеством "движущихся частей", который должен к тому же взаимодействовать с внешним миром. Изучите основы работы с пакетом Firebase и сделайте первые шаги во взаимодействии с облачным сервисом. Начните с разработки игр, и вы быстрее поймете, как построены блоки для игрового движка Flame. Почему я написал эту книгу Я впервые познакомился с Flutter, когда моя жена приступила к изучению этой технологии при помощи курса по разработке на Flutter, который был подготовлен Google. Главное, что мне запомнилось, — скорость разработки и то, насколько красиво выглядели приложения. Быстрое повышение производительности было впечатляющим, и меня увлекло построение простых мультиплатформенных приложений. Начиная изучать эту новую технологию, я столкнулся с несколькими вещами, которые были неочевидны или трудны для запоминания. И мне захотелось иметь некую книгу рецептов, лежащую под рукой. Сейчас в Сети доступны более продвинутые курсы, но давний вопрос остается: как сделать то или иное во Flutter? Для одних читателей эта книга станет дополнением знаний, помогающих создавать качественные приложения. Для других она будет чем-то вроде "защитного одеяла", которое сможет прикрыть и поддержать вас на пути Flutter-разработчика. Как организована эта книга Начало работы с любым языком программирования может сопровождаться некоторой неуверенностью, т. к. вы пока не знаете, с чего начать и что вам нужно освоить. Хотя я, как автор, хочу, чтобы вы прочитали книгу от первой до последней страницы, я понимаю, что скорее всего вы сразу откроете главы, посвященные непосредственно Flutter. Учитывая это, я разбил книгу на разделы, чтобы дать возможность погружаться в материал, как вам будет удобнее. Далее я перечислю эти разделы: главы 1 и 2 представляют собой общее введение в язык Dart, которое поможет вам в работе с такими основами, как переменные и управление потоком; главы 3–6 позволят вам быстро погрузиться в важные элементы Dart, что позволит вам использовать язык продуктивно; главы 7–14 посвящены языку Flutter и демонстрируют основы виджетов экранного рендеринга. Я догадываюсь, что этот раздел будет пользоваться большим вниманием в процессе разработки приложений, которые требуют создания виджетов и обработки данных; главы 15 и 16 посвящены облачной работе, особенно с Firebase, для добавления возможности аутентификации, взаимодействия с базами данных и хостингом; в главе 17 описан игровой движок Flame и особенности этого пакета. Если у вас появится свободное время, то этот материал пригодится вам для создания игры Frogger;


12 | Предисловие в Приложении рассказывается о том, что вам нужно знать для настройки среды, например об установке Flutter-фреймворка, использовании Flutter Doctor и работе в интегрированной среде разработки (IDE). Соглашения об используемых обозначениях В книге приняты следующие типографические приемы, улучшающие восприятие материала: Курсив — для обозначения новых терминов. Полужирный шрифт — для обозначения адресов электронной почты и адресов URL. Моноширинный шрифт — для листингов, ссылок на программные элементы внутри параграфов, таких как переменные, имена функций, базы данных, типы данных, переменные среды, операторы и ключевые слова. Моноширинный полужирный шрифт — для обозначения команд или другого текста, который должен ввести пользователь. Моноширинный курсив — для обозначения текста, который должен быть заменен значениями, введенными пользователем, или значениями, определяемыми контекстом. Этот элемент обозначает общее замечание. Онлайн-обучение O’Reilly Более 40 лет O'Reilly Media предоставляет материалы по технологиям, бизнес-тренингу, научным знаниям и идеям, помогающим компаниям добиться успеха. Мы располагаем уникальной сетью экспертов и инноваторов, которые делятся экспертными знаниями посредством книг, статей и нашей онлайновой обучающей платформы. Платформа онлайн-обучения O'Reilly предоставляет доступ по требованию к обучающим курсам в режиме реального времени, курсам углубленного обучения, интерактивным средам программирования, а также предлагает обширную коллекцию текстовых и видеоматериалов издательства O'Reilly и более чем 200 других издателей. Для дополнительной информации посетите наш сайт по адресу https://oreilly.com. Наши контакты Пожалуйста, направляйте ваши комментарии и вопросы, касающиеся этой книги, издателю:


Предисловие | 13 O’Reilly Media, Inc. 1005 Gravenstein Highway North Sebastopol, CA 95472 800-998-9938 (США и Канада) 707-829-0515 (международный или местный) 707-829-0104 (факс) У этой книги есть своя веб-страница, где мы помещаем ошибки, примеры и дополнительную информацию. Вы можете найти ее по адресу: https://oreil.ly/fl--dt-ckbk. Адрес электронной почты для комментариев и технических вопросов: [email protected]. Прочитать новости и информацию о наших книгах и курсах можно здесь: https://oreilly.com. Ищите нас в LinkedIn: https://linkedin.com/company/oreilly-media. Следуйте за нами в Twitter1 : https://twitter.com/oreillymedia. Смотрите нас в YouTube: https://www.youtube.com/oreillymedia. Благодарности Это издание посвящено моей любимой жене, которая вдохновила меня изучить Flutter, потому что только таким образом ей удалось привлечь меня к исправлению ошибок в созданных ею приложениях. Спасибо моим домочадцам, которые, несмотря на то, что глава семьи был занят написанием этой книги, всегда находили время завести погромче музыку или собраться поболтать, когда я был глубоко сконцентрирован на книге. Однако, если серьезно, спасибо Дону, Бейли, Эллиоту, Ноа и Амелии. В течение года работа над книгой вышла за рамки обычного проекта — она стала вдохновением. Особая благодарность Дилану Пеку (Dylan Peck), Кейси Палович (Casey Palowitch), Алессандро Палмиери (Alessandro Palmieri) и Эндрю Брогдон (Andrew Brogdon) за поддержку и возможность представить Flutter сообществу разработчиков Google. Я высоко оцениваю эти крайне полезные встречи и консультации. Я также хочу поблагодарить технических рецензентов — Алекса Мура (Alex Moore), Роба Эдвардса (Rob Edwards) и Маджида Хаджяна (Majid Hajian) — за ценную информацию и отзывы. Написать книгу нелегко, но при этом очень полезно и приятно общаться с людьми, которые хотят потратить свое свободное время, чтобы помочь тебе донести до читателей свои идеи. Я действительно ценю усилия и время, потраченное каждым из вас. Моя глубочайшая благодарность Джеффу Блейелу (Jeff Bleiel) за то, что он был фантастическим редактором и человеком, сделавшим процесс написания очень приятным и значительно менее стрессовым, чем это могло бы быть. Благодарю также Зана МакКвода (Zan McQuade) и Джонатона Овена (Jonatho Owenn) из издательства O'Reilly. 1 Организация запрещена в РФ. — Ред.


ГЛАВА 1 Переменные Dart В этой главе мы изучим основные приемы работы с переменными Dart. Как можно было ожидать, Dart предлагает богатый набор типов данных. Чтобы ускорить изучение языка, жизненно важно знать эти базовые типы. Если вы знакомы с использованием переменных в других языках программирования, то вам не составит труда понять применение переменных в Dart. Возвращайтесь к этой главе как к удобному справочнику, который поможет закрепить ваши знания о переменных прежде, чем вы приступите к более сложным темам. Если вы новичок, эта глава познакомит вас с основами. В конечном счете глава представляет собой краткое техническое руководство, сопровождающее вас на всем пути изучения Dart/Flutter. В этой главе примеры кода являются самостоятельными и ориентированы на типичные варианты использования переменных. Мы начнем с обсуждения четырех основных типов данных (int, double, bool и String). Затем мы научимся сообщать Dart, какими мы хотим сделать наши переменные (например, final, const или null). Мы также затронем тему неизменяемости, которая относится к способности переменной изменять свое значение. Неизменяемая переменная (или константа) — это особая переменная, значение которой нельзя изменить. В Dart, ключевые слова const и final делают переменную неизменяемой. Разница между этими ключевыми словами связана с тем обстоятельством, в какой момент определяется переменная — во время компиляции кода или в процессе его выполнения. На этапе компиляции определяются переменные типа const, а на этапе выполнения — переменные типа final. Начиная с версии Dart 2.0, язык является типобезопасным, следовательно, после объявления переменной ее тип не может быть изменен. Например, если переменная объявлена как double, то ее нельзя использовать как int без явного приведения. Но прежде чем подробнее рассмотреть работу с переменными, мы должны убедиться в правильной настройке среды программирования. 1.1. Выполнение приложения Dart Задача Вы хотите выполнить приложение Dart.


Переменные Dart | 15 Решение Код Dart может запускаться в вашей среде после установки набора средств разработки (SDK). Установка SDK описана в Приложении. Откройте сессию на терминале, чтобы вводить команды. Если вы используете интегрированную среду разработки (IDE), запустите терминал в IDE. Теперь подтвердите наличие Dart на вашем устройстве, проверив версию Dart и выполнив следующую команду: dart --version Если вы получите успешный ответ, то увидите установленную версию SDK и наименование платформы, на которой вы работаете. Если команда не выдает ответа, проверьте установку SDK на вашем устройстве. Теперь в вашем редакторе создайте новый файл с именем main.dart и следующим контентом: void main() { print('Hello, Dart World!'); } Запустите этот пример кода из командной строки: dart main.dart Эта команда должна вывести "Hello, Dart World!". Обсуждение Команды Dart доступны как часть установленного Dart SDK. В предыдущем примере команда запускает файл main.dart. Приложения Dart имеют расширение dart и могут запускаться как из командной строки, так и из IDE (например, Android Studio или VS Code). ПРИМЕЧАНИЕ. Ни Andrid Studio, ни VS Code не имеют предварительно установленной функциональности Dart/Flutter. Вам нужно поставить соответствующий плагин (в дополнение к установленному SDK) прежде, чем вы будете выполнять какой-либо код. Если вы не хотите устанавливать Dart в вашей среде, воспользуйтесь онлайновым редактором DartPad, который можно найти по адресу: https://dartpad.dev. Если вам не удается выполнить команду Dart, причина заключается, скорее всего, в некорректной установке SDK. Ознакомьтесь с последней версией инструкции по установке на ваше устройство. 1.2. Работа с целыми числами Задача Вы хотите сохранить целое число.


16 | Глава 1 Решение Используйте целочисленную переменную для хранения числа без десятичной точки. Если вы хотите задать целое значение 35, объявите переменную следующим образом: void main() { int myVariable = 35; print(myVariable); } В языке Dart для указания целых чисел предусмотрен тип int. В предыдущем примере кода тип данных (int) является первой частью декларации. Далее указывается метка (имя переменной) (например, myVariable). И наконец, мы присваиваем переменной значение — в рассмотренном случае 35. Чтобы использовать тип данных, объявляется переменная, например myVariable. Переменная — это метка, указывающая на созданный тип данных. Как только переменная станет доступной, вы можете присвоить ей значение. В приведенном примере целое число 35 присваивается переменной myVariable. Далее следует команда print для вывода значения этой переменной. Обсуждение Dart следует традиционному шаблону объявления переменной. Префикс указывает на тип данных, который будет выбран, затем следует метка (имя) переменной, а далее необязательное значение. В рассмотренном примере указан тип данных int. Целые числа представляются числами без десятичной точки. Типичный случай употребления int — это число, не требующее десятичной точки (т. е. без указания точности). Целое число представляется как 64-битовое целочисленное значение. Данные типа int — это подтип num, который включает базовые операции, например сложение, вычитание и т. п. Здесь имя переменной представляет собой ссылку на данные типа int. В нашем примере используется метка myVariable. Когда вы будете именовать переменные, старайтесь задавать имена, соответствующие назначению переменных. Для завершения декларации переменной ей присваивается значение 35. Мы присваиваем значение 35 и ожидаем, что при ссылке на эту переменную мы получим целое значение 35. Если бы целочисленная переменная не была инициализирована, то ее значение было бы недоступно. В такой ситуации Dart возвратит ошибку, означающую, что мы пытаемся обратиться к переменной, не допускающей значения null (non-nullable variable). По сути, это означает, что мы обращаемся к переменной, которой не присвоили значение. В большинстве случаев это ошибка, о которой нам услужливо сообщит компилятор Dart. Если же вам действительно требуется переменная, допускающая значение null, то придется сообщить Dart, каким образом поступить в этой ситуации. Вы узнаете больше о работе со значением null в Рецепте 1.9.


Переменные Dart | 17 1.3. Работа с дробными числами Задача Вы желаете сохранить число с десятичной точкой. Решение Используйте переменную типа double (двойной точности) для хранения числа, включающего десятичную точку. Если вы хотите сохранить переменную типа double со значением 2.99, создайте следующую декларацию: void main() { double myVariable = 2.99; print(myVariable); } Сначала, как обычно, укажите перед переменной нужный тип, т. е. double. Далее требуется метка переменной, т. е. myVariable. Затем присвойте значение, в приведенном примере это 2.99. Обсуждение В предыдущем примере мы начали с обозначения типа данных, т. е. double. Далее мы продолжили указанием имени переменной (myVariable) и завершили опциональным присвоением переменной значения. Типичный случай использования типа double — это число, требующее определенной точности. Тип double представляет собой 64-битовое число с плавающей точкой. Double — это подтип num, который включает базовые операции, например сложение, вычитание и т. п. 1.4. Работа с логическими значениями Задача Вы хотите сохранить значение true (истина) или false (ложь). Решение Для хранения переменных true/false предназначен тип bool. Объявите логическую переменную, задав ключевое слово bool, далее указав метку (имя) переменной, например myVariable. Закончите объявление присвоением значения true или false. Пример: void main() { bool myVariable = true;


18 | Глава 1 print(myVariable); } Обсуждение В рассмотренном примере мы начали с обозначения типа данных, т. е. bool. Далее мы указали имя переменной и опционально присвоили ей значение. Тип bool мы применяем в сценариях, использующих понятия "истина/ложь". Заметьте, что true и false являются в Dart зарезервированными словами. Зарезервированный в данном контексте означает, что слово имеет строго определенный смысл с точки зрения всего языка. Данные типа bool участвуют в логических операциях, например "И", равенство, "ИЛИ", "исключающее ИЛИ". 1.5. Работа со строками Задача Вам нужно сохранить последовательность символов. Решение Используйте переменную типа String для хранения текста. Пример объявления String: void main() { String myVariable = "I am a string"; String myVariable2 = """ I am a multiline String """; print(myVariable); } Обсуждение Начните с указания требуемого типа данных, т. е. String. Строка применяется для представления последовательности символов, которая может включать как цифры, так и буквы. Заметьте, что название типа данных String начинается с заглавной буквы. Указание прописной буквы здесь — частая ошибка новичков. Для объявления типа String потребуется имя переменной, указывающее на связанное с ней значение. Присвоение значения при объявлении не является обязательным. Типичный случай применения типа данных String — работа с текстом. Тип String в Dart использует 16-битовый Unicode-формат (UTF-16). Тип String применяется


Переменные Dart | 19 для представления текстовых символов, но благодаря кодировке поддерживает также и расширенный набор символов, например эмоджи. С типом данных String для идентификации текста допускаются одинарные или двойные кавычки. Если вам нужен многострочный текст, применяйте тройные кавычки. В рассмотренном примере продемонстрировано использование двойных и тройных кавычек. 1.6. Вывод информации на консоль Задача Вы хотите визуализировать результат работы приложения Dart. Решение Используйте оператор печати print для отображения информации, которую выводит приложение. Оператор print может выводить как статическое (например, строковый литерал), так и переменное содержимое. Пример вывода статического контента: void main() { print('Hello World!'); } Пример вывода содержимого переменной: void main() { int intVariable = 10; var boolVariable = true; print(intVariable); print('$intVariable'); print('The bool variable is $boolVariable'); } Обсуждение Применяйте символ $ для ссылки на переменную внутри оператора печати. Префикс $ сообщает Dart, что задана переменная, которая должна замениться на свое значение. Оператор печати полезен в ряде сценариев. Вывод статического содержимого не требует каких-либо дополнительных действий для отображения информации. В случае статического контента заключите значение в кавычки, а оператор печати позаботится об остальном. Для вывода значения переменной она должна иметь префикс $. В Dart вы можете таким образом указать, что хотите увидеть содержимое переменной. Во втором


20 | Глава 1 примере показаны три распространенных способа ссылки на переменные в операторе печати. Dart сообщит, требуются ли скобки. Как правило, нет. Однако, если ваша переменная имеет сложную структуру, убедитесь, что вы ссылаетесь на нужный элемент. 1.7. Работа с постоянной переменной (на этапе компиляциии) Задача Вам требуется создать переменную, которую нельзя изменить. Решение Используйте ключевое слово const для создания переменной, которую нельзя переопределить и значение которой будет определено во время компиляции. Пример: void main() { const daysInYear = 365; print ('There are $daysInYear days in a year'); } Обсуждение В Dart объект типа const представляет значение, которое не может быть изменено. Укажите ключевое слово const, если переменная не подлежит изменению. В рассмотренном примере объявляемая переменная получает число 365 в качестве значения, и оно не будет меняться в процессе работы приложения. Если бы вы попытались изменить значение в приложении, то увидели бы ошибку компиляции, указывающую на то, что присвоение не может быть выполнено по причине объявления этой переменной как const. Использование const — это хороший способ уменьшить количество ошибок в вашем приложении. Объявление переменных как const повышает надежность компиляции, т. к. в процессе компиляции происходит явная проверка определения переменных. 1.8. Работа с постоянной переменной (на этапе выполнения) Задача Вы хотите создать переменную, которую нельзя изменить, но вам не известно ее значение, пока приложение выполняется.


ГЛАВА 3 Использование функций В этой главе мы выйдем за рамки основ Dart и познакомимся с функциями. Как вы, возможно, заметили, мы уже использовали несколько функций (например, main и print). В этой главе мы рассмотрим основные случаи применения функций. Продвижение к более сложным приложениям определенно потребует от разработчика выхода за рамки простых конструкций. Как минимум желательно иметь знания в сфере некоторых основных концепций и алгоритмов. В процессе изучения этой главы вы познакомитесь с основами изоляции кода. Главное предназначение функции — это группировка инструкций. Глава начинается с иллюстрации определения функции без параметров и возвращаемого значения. В большинстве случаев такое простое определение вам не понадобится. Однако это полезно для учебных целей. Далее вы познакомитесь с параметрами и возвращаемыми значениями. На этом этапе вам станет понятнее, почему добавление параметров и возвращаемых значений настолько эффективно и почему желательно следовать этому шаблону. Ближе к концу главы вы увидите примеры других способов использования функций. Вы убедитесь в том, что с ростом вашего опыта в разработке параллельно будут улучшаться и навыки в применении функций. 3.1. Объявление функций Задача Вам требуется общее название для группы инструкций, выполняющих определенную задачу. Решение Объявите функцию, объединяющую инструкции, которые выполняют вашу задачу. В следующем примере функция getCurrentDateTime служит для вывода значений даты и времени: void main() { getCurrentDateTime(); } void getCurrentDateTime() { var timeLondon = DateTime.now();


Использование функций | 33 print('London: $timeLondon'); } Обсуждение Отправная точка приложения в Dart — это функция main(). Стандартный код не принимает параметров и ничего не возвращает (функция предваряется ключевым словом void). С помощью этой функции мы можем как создавать, так и вызывать другие функции для организации работы всего нашего приложения. В предыдущем примере мы создаем служебную функцию с именем getCurrentDateTime. Обратите внимание на то, что функция объявлена без параметров и, как и функция main(), ничего не возвращает. Роль функции getCurrentDateTime состоит в получении текущего значения DateTime. Для этого функция вызывает библиотечную функцию DateTime.now(), которая возвращает текущее время и дату. Хотя вы могли бы поместить код непосредственно в функцию main, теперь у нас есть способ получить доступ к текущей дате, которую можно легко добавить в другие программы. Так как мы сгруппировали нужную функциональность в отдельную функцию, ее можно изолировать и применять по мере необходимости в других программах. Изолирование частей кода — полезный навык, который позволит вам повторно использовать этот фрагмент кода в дальнейшем. 3.2. Добавление параметров Задача Вы хотите передать функции некоторую информацию. Решение Передачу функции информации осуществляют с помощью параметров. В следующем примере функции передается параметр, являющийся частью управления потоком: void main() { getCurrentDateTime(-7); } void getCurrentDateTime(int hourDifference) { var timeNow = DateTime.now(); var timeDifference = timeNow.add(Duration(hours: hourDifference)); print('The time now is: $timeNow'); print('The time minus 7 hours is: $timeDifference'); }


34 | Глава 3 Обсуждение В приведенном примере параметр, переданный функции, определяет некоторое действие. Функция рассчитывает разницу в часах, получая текущее время, возвращаемое DateTime.now(). Учитывая, что мы добавили параметр в функцию, теперь в нем можно явно указать требуемую разницу в количестве часов. Таким образом мы расширили применимость этой функции. Однако из-за того, что функция не возвращает никакого значения, она не такая гибкая, как могла бы быть. Использование параметров повышает гибкость функции за счет добавления переменной. Добавление переменных в структуру функции делает функцию более общей по своей природе. Создание обобщенных функций — хороший подход, позволяющий сократить объем программного кода, требуемого для выполнения задачи. 3.3. Использование необязательных параметров Задача Вы хотите, чтобы функция имела переменное количество параметров. Решение Используйте необязательный параметр. Dart поддерживает необязательные параметры, что позволяет их опускать. Доступны два типа необязательных параметров: именованные и позиционные. Пример именованных параметров: void main() { printGreetingNamed(); printGreetingNamed(personName: "Rich"); printGreetingNamed(personName: "Mary", clientId: 001); } void printGreetingNamed({String personName = 'Stranger', int clientId = 999}){ if (personName.contains('Stranger')) { print('Employee: $clientId Stranger danger '); } else { print('Employee: $clientId $personName '); } } Пример позиционных параметров: void main() { printGreetingPositional("Rich"); printGreetingPositional("Rich", "Rose"); }


Использование функций | 35 void printGreetingPositional(String personName, [String? personSurname]){ print(personName); if (personSurname != null){ print(personSurname); } } Обсуждение Dart предоставляет дополнительную гибкость в использовании параметров в функциях. Там, где параметры могут быть опущены, полезно рассмотреть возможность применения необязательных параметров. Именованные параметры позволяют включать имена переменных в объявление функции. Чтобы использовать параметр этого типа, вставьте необходимые значения в фигурные скобки. В первом примере необязательные параметры служат для передачи имени и идентификатора клиента. Если функция не снабжена этой информацией, она все равно будет работать должным образом, установив значение по умолчанию. При необходимости значения по умолчанию можно указать (например, int clientId = 999). Позиционные параметры работают аналогично обычным параметрам, с той разницей, что при необходимости их можно опустить. Во втором примере второй параметр определяется как позиционный параметр с помощью квадратных скобок. Кроме того, Dart позволяет определить переменную как потенциальное значение null путем включения символа ?. Как именованные, так и позиционные параметры обеспечивают повышенную гибкость ваших функций. Это удобно в различных сценариях, где необходимы, но не обязательны параметры (например, в объекте person, где имя и фамилия обязательны, но отчество необязательно). 3.4. Возвращаемые значения Задача Вы хотите возвратить значение, вычисленное вашей функцией. Решение Используйте именованную функцию, которая вычисляет и возвращает значение вызывающей функции. Это один из общепринятых механизмов группировки инструкций. Пример объявления функции, которая возвращает значение: void main() { DateTime timeNow = getCurrentDateTime(0); DateTime timeDifference = getCurrentDateTime(-7);


ГЛАВА 5 Объектно-ориентированный Dart В этой главе мы представим объектно-ориентированные методы работы с классами и продемонстрируем, как это можно совместить с Dart. В процессе изучения данной темы вы исследуете как объявление, так и расширение объектов. Эти приемы важны, поскольку Dart — объектно-ориентированный язык. Изучение основ даст хороший старт повышению вашего уровня как программиста и упростит использование кода, написанного другими. Мы начнем с краткого обзора основной терминологии, связанной с объектноориентированным программированием применительно к Dart. Затем разберемся, как ввести понятие class в ваши навыки программиста. Мы также обсудим следующие вопросы: основы объектно-ориентированного программирования; необходимость инициализации класса с помощью конструктора; поддержку наследования через ключевое слово extends; определение сигнатуры класса с использованием интерфейса; агрегацию функциональности класса с помощью миксина (mixin). По мере усложнения вашей разработки для достижения цели вы сможете создавать собственные пользовательские классы. Чтобы научиться эффективно применять классы, вам придется подняться на довольно крутой склон, так что старайтесь делать небольшие шаги. Со временем в решении ваших задач вы научитесь использовать очень сложные конструкции и приемы. 5.1. Введение в объектно-ориентированный Dart Задача Вы хотите применить объектно-ориентированное программирование на Dart для создания многоразовых компонентов. Решение Используйте объектно-ориентированные методы Dart для разработки кода, отражающего компонуемые объекты, которые позволяют создать вашу целевую модель. Dart поддерживает объектно-ориентированную технологию и поощряет


Объектно-ориентированный Dart | 49 разработку на ее основе алгоритмов и структур данных, нужных для создания вашего приложения. Обсуждение Обучение объектно-ориентированной разработке значительно разовьет ваше умение использовать Dart и Flutter. Научиться создавать объекты — это базовый навык, который поможет вам лучше понять, как связать алгоритмы со структурами данных. Обычно объект необходимо инициализировать с помощью специального метода, который называется конструктором. Конструктор отвечает за установку свойств внутри объекта во время выполнения его инициализации. Объект — это не что иное, как группировка кода и типов данных в одну репрезентативную структуру. Например, класс book и инициализированный объект (созданный экземпляр объекта) могут иметь заголовок, имя автора и наименование издателя в качестве свойств. На рис. 5.1 класс book обеспечивает определение, а объект book — это версия класса во время выполнения кода. Класс book также может иметь другие свойства (например, isbn) или методы для возвращения (получения) и обновления (установки) связанных с ним свойств. Удобство объединения данных и кода в определении класса станет вам более привычным по мере работы с языком Dart. Рис. 5.1. Пример класса book Приступая к объектно-ориентированному программированию на Dart, обязательно изучите варианты использования наследования (см. Рецепт 5.4), выполнения (см. Рецепт 5.5) и расширения (см. Рецепт 5.6), чтобы научиться выбирать наиболее подходящий шаблон проектирования для реализации вашего будущего сценария. 5.2. Создание класса Задача Вы хотите создать объект класса, который предоставляет как данные, так и функциональные возможности.


50 | Глава 5 Решение Используйте класс для объединения информации в новый объект, обеспечивающий как хранение переменных, так и функциональность для обработки информации. Вот пример того, как объявить класс в Dart: const numDays = 7; class DaysLeftInWeek { final int currentDay = 0; DaysLeftInWeek(){ currentDay = DateTime.now().weekday.toInt(); } int howManyDaysLeft(){ return numDays - currentDay; } } Обсуждение Dart — объектно-ориентированный язык, в котором есть класс Object для всех объектов Dart, кроме объектов null. В результате объект, не допускающий значения null, является подклассом Object. По мере ознакомления с написанием кода Dart создание классов станет вашей второй натурой. Объектно-ориентированное программирование предоставляет средства для моделирования идей и связанного с ними поведения объекта. Классы предоставляют модель, в которой вы можете определить как данные, так и функции доступа к включенным в модель данным. В примере на рис. 5.2 класс DaysLeftInWeek предназначен для определения числа дней, оставшихся в неделе. Рис. 5.2. Объявление класса В определении класса, показанного на рис. 5.2, мы видим, что он располагает свойством currentDay и методом howManyDaysLeft. Ключевое слово class служит для указания на следующее далее определение, включающее элементы как для переменных, так и для функций. Конструктор класса, DaysLeftInWeek, имеет то же имя, что и класс, и вызывается при инициализации экземпляра объекта. Используйте конструктор класса для выполнения разовых действий в момент создания класса. Внутри класса переменная currentDay объявлена как final int, следовательно, ее значение будет определено во время исполнения и будет представлять собой це-


Объектно-ориентированный Dart | 51 лое число. В дополнение объявлен метод howManyDaysLeft для выполнения вычислений. 5.3. Инициализация класса с помощью конструктора Задача Вы хотите выполнить серию инструкций каждый раз, когда создается новый объект класса. Решение Примените конструктор класса для инициализации экземпляра объекта. Кроме того, инициализация позволяет установить разумные величины значений класса по умолчанию. Вот пример, демонстрирующий объявление и использование конструктора класса1 : const numDays = 7; final class DaysLeftInWeek { int currentDay = 0; DaysLeftInWeek(){ currentDay = DateTime.now().weekday.toInt(); } int howManyDaysLeft(){ return numDays - currentDay; } } void main() { DaysLeftInWeek dayCalculator = DaysLeftInWeek(); print ('Today is day ${dayCalculator.currentDay}'); print ('${dayCalculator.howManyDaysLeft()} day(s) left in the week'); } Обсуждение В этом примере класс применяется для определения числа оставшихся дней в неделе. При объявлении класса определяются как переменные, так и функции. На рис. 5.3 показано, что класс объявляется путем вызова этого класса. Конструктор принимает то же имя, что и класс, и вызывается при создании экземпляра класса. В этом примере конструктор присваивает переменной класса currentDay значение текущей даты. Обратите внимание, что в классе DaysLeftInWeek определена функция с тем же именем, что и у класса. 1 В этом примере в присвоении значения переменной currentDay опущено ключевое слово this. Практика показывает, что ключевое слово this не должно использоваться в Dart, кроме случаев, когда оно обязательно.


ГЛАВА 7 Знакомство со средой разработки Flutter В этой главе мы начнем наше путешествие со знакомства со средой разработки Flutter и сосредоточимся на некоторых ее основах. На мой взгляд, лучшая отправная точка в работе с приложением Flutter — это общее понимание того, как ваше приложение будет выглядеть и работать. Если вы имеете опыт работы в сфере дизайна, возможно, вам больше знаком термин wireframe (каркас). В любом случае нам бы хотелось создать наглядную и репрезентативную схему дизайна приложения. Освоившись с разработкой интерфейсов с помощью Flutter, вы сможете найти хороший источник вдохновения на таких сайтах, как dribbble.com. Обычно я просматриваю сайты, подобные этому, чтобы выяснить, как можно сделать приличный дизайн, а затем отображаю его с помощью серии картинок (т. е. каркасов), которые я хочу увидеть на экране. Команда Flutter прикроет вас, поскольку они предоставляют широкий спектр шаблонов, которые помогут вам приступить к написанию кода вашего приложения. Как только у вас появится начальный вариант кода, вам нужно понять разницу между виджетами с сохранением и без сохранения состояния, что будет постоянным вопросом по мере разработки ваших проектов. К счастью, способность Flutter создавать все более сложные интерфейсы означает, что потраченное на это время окупится в будущем. Когда мы говорим о Flutter, нам действительно нужно понимать виджеты и то, как они используются для рендеринга экранных компонентов. Прежде чем определить, что такое виджет, мы обсудим методы макетирования интерфейса и создания шаблонного приложения Flutter; затем мы выясним, как виджеты применяются для построения пользовательского интерфейса. Наконец, мы кратко рассмотрим древовидную структуру виджета, чтобы завершить наше понимание структуры взаимодействия между компонентами Flutter. 7.1. Макетирование интерфейса приложения Задача Вам нужен способ имитировать интерфейс, чтобы построить макет будущего приложения Flutter.


Знакомство со средой разработки Flutter | 71 Решение Для разработки вашего приложения используйте графический пакет. Создание каркаса приложения поможет вам лучше понять, как оно будет работать. В табл. 7.1 приведены примеры пакетов, которые могут быть полезны, в зависимости от вашего бюджета и целей использования. Таблица 7.1. Примеры графических пакетов Название пакета Ссылка Цена Описание Excalidraw https://excalidraw.com Бесплатно Общий инструмент графического веб-дизайна Figma https://www.figma.com Есть бесплатная версия Интерактивное проектирование и сборка шаблонов пользовательского интерфейса без кода FlutterFlow https://flutterflow.io Есть бесплатная версия Интерактивные шаблоны пользовательского интерфейса и компоненты, генерирующие Flutter-код Обсуждение Имитация интерфейса — отличный способ начать работу с таким визуальным фреймворком, как Flutter. Существует множество способов создания интерфейса, начиная от бесплатных онлайн-инструментов и заканчивая специализированными приложениями, созданными конкретно для Flutter. При создании макета приложения я стремлюсь представить будущий интерфейс, имея в виду виджеты, которые я наметил использовать. Это облегчает создание определенных конструкций. Если вы имеете дело со сложными проектами, понимание требований приложения приводит к более чистому интерфейсу и лучшей эстетике дизайна. На рис. 7.1 приведен пример использования пакета Excelidraw, помощью которого я создал свое первое приложение на Flutter. Для отражения функциональности я изобразил на этом рисунке две веб-страницы и панель навигации. Я также показываю, как должны работать экранные переходы. Разбивка интерфейса на части — хороший способ узнать, как взаимодействуют различные виджеты. Кроме того, изучение правильной терминологии для виджетов определенно помогает найти подходящее решение. Хотя приложение не очень сложное, с его помощью я изучил основы создания виджетов с помощью Flutter. На рис. 7.1 вы видите очень распространенный тип интерфейса, часто встречающийся в приложениях Flutter. Важно научиться применять такие виджеты, как ListView, Text и Image, а также управлять жестами и навигацией.


72 | Глава 7 Рис. 7.1. Каркас макета дизайна 7.2. Создание шаблонного проекта Flutter Задача Вы хотите создать новое приложение Flutter, используя шаблонный код. Решение Примените шаблон Flutter в качестве отправной точки вашей разработки. Вам не нужно начинать с нуля, потому что Flutter предоставляет целый ряд шаблонов для разработки приложений. Доступно несколько видов шаблонов, которые обеспечивают базовую настройку приложения. В последние версии фреймворка Flutter были добавлены некоторые многофункциональные примеры. Этот стандартный код позволит улучшить ваши навыки и облегчит понимание общепринятых моделей, созданных экспертами. В табл. 7.2 приведены несколько шаблонов, имеющихся во фреймворке Flutter, которые помогут вам начать работу. Таблица 7.2. Примеры шаблонов фреймворка Flutter Тип шаблона Описание app Команда Flutter create, создающая приложение Flutter по умолчанию module Эта опция позволяет создать модуль, который может быть интегрирован в приложение package Эта опция позволяет создать проект Flutter, доступный для совместного использования plugin Эта опция предоставляет API для использования с платформами Android и iOS skeleton Эта опция предоставляет пример лучшего приложения, основанный на Detail View


Знакомство со средой разработки Flutter | 73 Добавляя команду template, т. е. -template или -t, вы можете указать Flutter, что при создании приложения должен быть применен шаблон. Далее приведены несколько примеров шаблонов. Шаблон для создания приложения по умолчанию: flutter create my_awesome_app Для создания модуля: flutter create -t module my_awesome_module Для создания пакета: flutter create -t package my_awesome_package Для создания подключаемого модуля (плагина): flutter create -t plugin my_awesome_plugin --platforms web –platform android При создании плагина вы должны указать платформу, которая им будет поддерживаться. Для каждой добавляемой платформы требуется добавление префикса -platform. Шаблон для создания скелетона1 : flutter create -t skeleton my_awesome_skeleton Обсуждение В представленных примерах вы заметите, что Flutter предлагает много вариантов шаблонного кода, который поможет вам начать работу. Центральный элемент — команда flutter create, которая предназначена для того, чтобы вы могли указать тип кода, который должен быть сгенерирован, например модуль, пакет, плагин. У flutter create также есть опция, которая позволяет сгенерировать код в автономном режиме. Чтобы использовать эту опцию, просто введите flutter create -offline [действие]. Я нахожу эту опцию очень удобной при работе там, где нет устойчивого подключения к Интернету. Однако для автономной работы потребуется наличие pub cache, и я видел, что он иногда выходит из строя при работе в Android Studio. Когда вы создаете проект на основе шаблона, нужное устройство должно быть доступно на вашем компьютере. В дополнение к шаблонам вы также можете ссылаться на примеры кода с веб-сайта документации по API (https://docs.flutter.dev/). Чтобы использовать код с сайта, вам необходимо указать идентификатор образца кода, расположенный на странице нужного виджета. В следующем примере код можно найти на веб-странице класса GestureDetector (https://api.flutter.dev/flutter/widgets/ GestureDetector-class.html): flutter create -s widgets.GestureDetector.1 my_awesome_sample 1 Скелетон (скелетная загрузка) — это техника, используемая в веб-разработке для улучшения впечатления пользователей при загрузке страницы. Вместо отображения пустого пространства или индикатора загрузки пользователь видит "скелет" страницы, который постепенно заполняется контентом. — Пер.


74 | Глава 7 Есть образцы кода, которые обеспечивают быстрый доступ к множеству онлайнконтента. Как разработчик, я лично рекомендую ориентироваться на веб-платформу в дополнение к платформе, для которой вы разрабатываете приложение. Включение веб-платформы имеет смысл, поскольку это предполагает очень эффективный метод тестирования приложений в браузере. Не говоря уже о том, что выполнять инкрементное тестирование в браузере очень быстро и легко. На этапе разработки такой подход, безусловно, может повысить скорость внедрения как небольших, так и крупных улучшений. 7.3. Удаление баннера отладки Flutter Задача Вы хотите удалить баннер отладки из вашего приложения Flutter. Решение Используйте свойство debugShowCheckModeBanner для удаления этого баннера. Вот пример приложения Flutter, демонстрирующего выключение свойства debug и соответствующего баннера: import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { const title = 'Debug Example'; return MaterialApp( title: title, home: Scaffold( appBar: AppBar( title: const Text(title), ), body: const Text("Removed Debug Banner"), ), debugShowMaterialGrid: false, debugShowCheckedModeBanner: false, ); } } Обсуждение В приведенном примере кода показано, как удалить флаг отладки из вашего приложения.


Знакомство со средой разработки Flutter | 75 Свойство debugShowCheckedModeBanner принимает логическое значение, определяющее, следует ли показывать уведомление. В приведенном примере сообщение "Debug" отключается путем установки для свойства значения false. По умолчанию Flutter для debugShowCheckedModeBanner задает значение true. Разработчики должны явно установить это значение как false, чтобы удалить временный баннер из приложений. В табл. 7.3 приведены различные значения для состояний приложения Debug и Release. Таблица 7.3. Значения свойств состояний приложения Режим Свойство Объяснение Debug debugShowCheckedModeBanner Баннером можно управлять с помощью логического значения. При установке значения true баннер будет отображаться; это значение по умолчанию для всех новых приложений. Изменение значения свойства на false приведет к удалению баннера из вашего приложения Release debugShowCheckedModeBanner Баннер не отображается в режиме Release, независимо от значения свойства Свойство debugShowMaterialGrid регулирует наложение координатной сетки на экран вашего приложения. Если вам нужно решить проблему с правильным размещением элемента на экране, этот параметр полезно временно включить. Значение по умолчанию для этого параметра — false, поэтому вам нужно включать его по мере надобности. Чтобы использовать этот параметр, ваше приложение должно находиться в режиме Debug. 7.4. Знакомство с виджетами Задача Вы хотите понять, как Flutter использует виджеты для обеспечения единого представления на нескольких платформах. Решение Виджеты — это компоненты, представляющие экранные элементы, такие как текст, изображения и списки. Когда вы начинаете работать с Flutter, непросто осознать тот факт, что большая часть кода может представлять собой виджет. Обсуждение Важное свойство виджетов Flutter заключается в том, что они поддаются компоновке, а следовательно, для создания новых виджетов вы можете расширить функциональность ранее разработанных. Возможность задействовать существующие виджеты невероятно эффективна, поскольку вам не нужно вникать в основные принципы и вы можете сразу приступить к использованию и компоновке существующих решений.


76 | Глава 7 Главное следует помнить, что класс widget — это неизменяемое описание пользовательского интерфейса, которое может быть расширено до элементов, связанных с деревом рендеринга. По большей части, создавая пользовательский интерфейс, вы будете использовать или комбинировать готовые виджеты, а также создавать новые виджеты для обеспечения требуемой функциональности. Интересный аспект этой работы — компоновка существующих виджетов для достижения желаемого результата. 7.5. Дерево виджетов Flutter Задача Вы хотите выяснить, как Flutter использует дерево виджетов для компоновки интерфейса пользователя. Решение С помощью виджетов Flutter создает экранное представление работы приложения. Комбинирование виджетов поможет получить красивые и многофункциональные пользовательские интерфейсы. Связь между виджетами строится с помощью древовидной структуры. Разрабатываемое представление зависит от используемых виджетов и порядка их применения. Обсуждение Дерево виджетов создает взаимосвязи между имеющимися компонентами. Типичное приложение Flutter будет основано на ряде виджетов, как показано на рис. 7.2. Рис. 7.2. Дерево виджетов


Знакомство со средой разработки Flutter | 77 Из дерева виджетов, показанных на рис. 7.2, видно, что MaterialApp является родительским элементом для всего приложения. Виджет Scaffold осуществляет связь с дочерними элементами, обеспечивающими различную функциональность. Один из наиболее важных аспектов разработки с помощью Flutter — рефакторинг кода, который должен привести в соответствие ваш код и дерево виджетов вашего приложении. У новичков, только начавших осваивать Flutter, нередко можно увидеть очень большие деревья виджетов, подобные изображенному на рис. 7.2. Распространенный подход заключается в выделении контекста сборки (и, более конкретно, цикла рендеринга) для повышения общей производительности рендеринга всего приложения. Чтобы приступить к рефакторингу кода, познакомьтесь с Рецептом 9.4. 7.6. Улучшение производительности рендеринга виджета Задача Вы хотите разобраться в том, как Flutter осуществляет рендеринг виджетов, чтобы увеличить производительность приложения. Решение Виджеты Flutter участвуют в цикле рендеринга, который предназначен для добавления различных компонентов на экран. Поскольку виджет может быть родительским по отношению к другим виджетам, иногда появляется необходимость в создании контекста сборки, который эффективно делегирует управление связанными виджетами и обеспечивает лучшую производительность. Обсуждение Если вы создадите очень сложную иерархию, то ее поддержание может оказаться дорогостоящим с точки зрения производительности приложения. Всякий раз, когда ваше приложение вызывается для отображения информации, оно будет пытаться определить, актуальна ли имеющаяся информация или требуется обновление данных. На рис. 7.3 рендеринг в цикле отслеживает любое изменение состояния, связанное с виджетом. Если найдено обновление, это вызовет перестройку связанного дерева виджетов для отражения изменений в построении контекста. Если иерархия вашего дерева виджетов слишком сложна, необходимо ее перестроить, что может положительно повлиять на общую производительность приложения. В частности, если вы включаете состояние в контекст сборки, возможно, это станет одним из распространенных узких мест в производительности при разработке


78 | Глава 7 вашего приложения Flutter. Выделение состояния в небольшой контекст сборки значительно повысит общую производительность, т. к. изменение состояния будет локализовано только в соответствующем виджете, а не во всем дереве виджетов. Рис. 7.3. Цикл рендеринга Flutter


ГЛАВА 8 Ассеты В этой главе мы рассмотрим добавление ассетов1 в ваше приложение Flutter. Во многих случаях вы захотите разместить ассеты для приложения в локальных папках. К счастью, Flutter располагает простым механизмом архивации таких файлов с помощью файла pubspec.yaml. Изучив эту главу, вы научитесь: создавать папку для ассетов; делать ссылку на изображение; создавать ссылку на папку изображения; делать ссылку на изображение в вашем приложении; добавлять шрифты в ваше приложение; импортировать пакет. Применение ассетов — это еще один шаг на пути к пониманию среды Flutter. Что касается меня, я всегда забываю, как добавлять изображения, так что, надеюсь, эта технология спасет вас от подобных трудностей. Добавление ассетов представляет собой хороший способ повторного использования компонентов, который легко расширит общую функциональность вашего приложения. В конце этой главы у вас должно быть достаточно опыта, чтобы без особых усилий выполнять все задачи, упомянутые в приведенном ранее списке. 8.1. Использование файла pubspec.yaml Задача Вы хотите понять, что представляет собой файл pubspec.yaml и как его лучше всего использовать при разработке во Flutter. Решение Файл pubspec.yaml — это файл централизованного управления средой Flutter. В нем содержится ряд настроек, которые отражают текущую версию SDK, зависимости, расположение ассетов и название приложения. 1 Ассеты (assets) — это компоненты, которые представляют собой уже готовые решения, созданные вами или другими людьми, например изображения, шрифты, скрипты и т. п. — Пер.


ГЛАВА 12 Межстраничная навигация Flutter В этой главе мы рассмотрим использование распространенных методов навигации по страницам. Межстраничная навигация очень важна при разработке любого приложения. К счастью, Flutter упрощает нам создание большей части этого интерфейса. До сих пор мы фокусировались на создании приложения с единственной страницей. Однако теперь вы, вероятно, захотите выйти за рамки этого базового варианта, чтобы дополнить его навигацией между несколькими страницами. Для начала мы сосредоточимся на распространенных шаблонах навигации. В этой главе вы узнаете: как использовать маршруты для перемещения между страницами; как добавить виджет боковой выдвижной навигации; как добавить виджет интерфейса вкладки; как добавить виджет нижней панели навигации; как передавать данные с помощью ключей. Возможность перемещаться между страницами с помощью встроенной навигации сделает внешний вид ваших приложений более профессиональным. Flutter предоставляет несколько способов навигации между информационными страницами, и, определенно, стоит научиться включать их в ваши собственные приложения. К концу этой главы вы познакомитесь с основами навигации по страницам с помощью маршрутов. 12.1. Добавление императивной межстраничной навигации Задача Вы хотите перемещаться между страницами, используя специфические инструкции навигации. Решение Примените навигацию Flutter, которая обеспечивает механизм перехода между страницами за счет маршрутов. Маршрут указывает на адрес страницы, к которой необходимо получить доступ. Переход между страницами требует наличия виджета


Межстраничная навигация Flutter | 147 MaterialPageRoute, который добавляет новую страницу в стек приложения, заменяя текущую страницу. Вот пример навигации между двумя разными страницами: import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { MyApp({Key? key}) : super(key: key); final List<String> items = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]; @override Widget build(BuildContext context) { const title = 'MyAwesomeApp'; return MaterialApp( title: title, home: Scaffold( appBar: AppBar( title: const Text(title), ), body: ListView.builder( itemCount: items.length, itemBuilder: (context, index) { return MyListView(items[index]); }, ), ), ); } } class MyListView extends StatelessWidget { const MyListView(this.title); final String title; @override


148 | Глава 12 Widget build(BuildContext context) { return ListTile( title: Text(title), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => MyDetails(title), ), ); }, ); } } class MyDetails extends StatelessWidget { const MyDetails(this.itemTitle); final String itemTitle; @override Widget build(BuildContext context) { const title = 'Details Page'; return Scaffold( appBar: AppBar( title: const Text(title), ), body: SafeArea( top: false, bottom: false, child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ SizedBox( height: 338.0, width: 800.0, child: Card( clipBehavior: Clip.antiAlias, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Divider(), Padding( padding: const EdgeInsets.all(10.0), child: Text(itemTitle), ) ], ), ),


Межстраничная навигация Flutter | 149 ), ], ), ), ), ); } } Обсуждение В приведенном примере событие onTap настроено для каждой позиции списка ListTile, поэтому при выборе элемента списка будет сгенерировано событие. Данное событие связано с объектом Navigator.push, который запрашивает отображение новой страницы. С помощью объекта Navigator V1 с императивной маршрутизацией переход между страницами значительно упрощается. Механизм императивной навигации предполагает наличие стека для перемещения по страницам. На рис. 12.1 навигация между страницами явно задана с помощью класса MaterialPageRoute. Рис. 12.1. Пример класса MaterialPageRoute За счет объекта MaterialApp необходимые значки навигации будут созданы автоматически. В этом случае стрелка "назад" отображается на экране без какого-либо дополнительного кодирования. Убедитесь, что определение виджета Scaffold, добавленное на страницу Details, не переопределяет MaterialApp. Navigator.push реализует механизм стека, в котором новые экраны добавляются и удаляются по мере перемещения пользователя между ними. Маршрутизация между экранами обрабатывается автоматически, поэтому вам, как разработчику, просто нужно указать страницу, которая будет использоваться в текущем контексте сборки. При возврате с новой страницы на старую приложение запустит механизм pop для перехода на предыдущую страницу:


ГЛАВА 16 Введение в облачные сервисы В этой главе вы узнаете, как интегрировать Flutter и Dart с облачными сервисами. Первый вопрос, который вы можете задать: зачем мне использовать облачные сервисы? В процессе создания более продвинутых приложений, выходящих за рамки мобильной или настольной платформы, вам нужно где-то запускать (размещать) свой программный код. Облачные сервисы позволяют вашему приложению получить доступ к множеству сложных готовых решений, таких как API, хранилище, аутентификация и базы данных. Но разве я не получаю это вместе с Firebase, спросите вы. Это так, но платформа Firebase — это всего лишь "закуска" перед "основным блюдом". В этой главе мы рассмотрим облачный сервис Google Cloud в качестве основы для примеров, однако изложенные методы применимы к решениям большинства облачных провайдеров. На этапе размещения приложения мы будем внедрять бессерверную технологию, позволяющую минимизировать конфигурацию инфраструктуры и в результате снизить накладные расходы. В этой главе вы узнаете: как управлять идентификацией и доступом; как использовать облачное хранилище в качестве серверной части; как разработать простой HTTP-сервер; как перенести приложение в контейнер; как разместить контейнер у облачного провайдера. Облачные сервисы продолжают развиваться, более того, они предоставляют разработчикам доступ к некоторым потрясающим сервисам по схеме "плати по мере использования". Гибкость и производительность, предлагаемые облачными провайдерами, избавят вас от частой головной боли при разработке. Цель этой главы — научить вас использовать преимущества платформы Firebase в полной мере. 16.1. Начало работы с провайдерами облачных сервисов Задача Вы хотите получить доступ к облачным ресурсам таких провайдеров, как Amazon Web Services (AWS), Micrisoft Azure или Google Cloud.


222 | Глава 16 Решение В услугах облачного провайдера обычно предусмотрен бесплатный уровень, позволяющий вам приступить к работе. Для начала вам необходимо зарегистрироваться у поставщика облачных услуг, чтобы получить доступ к предоставляемым продуктам. В этой главе мы продемонстрируем конкретные сервисы на примере Google Cloud. Мы укажем на случаи, когда нет подходящей альтернативы. Обсуждение Когда вы начинаете работать с поставщиком облачных услуг, вы можете почувствовать себя немного ошеломленным. Каждый из упомянутых облачных провайдеров предоставляет множество различных решений. Основными областями, на которых мы сосредоточимся, будут хранение данных и внедрение бессерверной инфраструктуры. Чтобы научиться с этим работать, нам нужно рассмотреть способы управления идентификацией и доступом, которые применяются для авторизации учетных данных в вашем новом облачном ресурсе. 16.2. Работа с идентификационными данными и управлением доступом Задача Вы хотите добавить пользовательский аккаунт, позволяющий получить доступ к облачным сервисам. Решение Используйте облако для предоставления параметров управления идентификацией и доступом. Установите ограничения на роли пользователя и на данные ему разрешения. Все ведущие игроки облачного рынка называют это управлением идентификацией и доступом. Обсуждение Управление идентификацией и доступом — это фундаментальная концепция при работе с любым облачным провайдером. В общем, вам необходимо понимать два важных ключевых элемента: идентификацию и доступ (рис. 16.1). Облачные провайдеры определяют характер разрешений, применимых к пользовательскому аккаунту, на основе учетных данных. Большинство провайдеров допускают использование аккаунта электронной почты в качестве учетных данных пользователя (т. е. для удостоверения личности). Чтобы сообщить учетные данные вашему провайдеру, введите их в соответствующую форму и выберите роль (т. е. вариант требуемого доступа), которая будет связана с этими учетными данными.


Введение в облачные сервисы | 223 Рис. 16.1. Идентификация и доступ У каждого облачного провайдера есть свой собственный метод добавления учетных данных для управления идентификацией и доступом. Процесс управления идентификацией и доступом выполняет две задачи. Во-первых, он регистрирует учетные данные пользователя — этот шаг сообщает системе, кто вы такой. Во-вторых, управление доступом служит для определения разрешений, назначенных вам как пользователю. Сочетание управления идентификацией и доступом обеспечивает основу любых действий, выполняемых пользователем на сервисе провайдера. Идентификация отражает учетные данные, использующиеся для доступа к облачному сервису провайдера, например это может быть учетная запись электронной почты, которая будет связана с вашей рабочей облачной средой. Для доступа к ресурсам и авторизации того, что разрешено делать в облаке, требуются идентификационные данные. Во многих отношениях доступ к облачным ресурсам аналогичен доступу к локальному компьютеру. После этапа идентификации следующим шагом является определение прав доступа пользователя. Доступ отражает характер разрешений, связанных с идентификацией. Понятие наименьших привилегий особенно важно в отношении учетной записи. Облачные провайдеры представляют несколько ролей, которые соответствуют применяемым сервисам. Введение уровня детализации дает конечному пользователю возможность сократить число разрешений только до тех, которые необходимы для выполнения конкретной задачи. У каждого облачного провайдера есть свои собственные роли и соответствующие разрешения для регулирования доступа к своим ресурсам. Понимание разницы между разрешениями доступа сделает вашу среду более безопасной. Важно не набирать лишние разрешения и следовать принципу наименьших привилегий, чтобы обеспечить безопасный доступ. Если вы намереваетесь работать с сервисами облачного провайдера, настоятельно рекомендуется создать для этой цели отдельную учетную запись. Совмещение учетной записи для личного аккаунта и бизнес-аккаунта хотя и удобно, но не обеспечивает разделения задач. Поэтому используйте уникальную учетную запись для деятельности, связанной с бизнесом, везде, где это практически возможно.


224 | Глава 16 16.3. Использование облачного хранилища для размещения объекта Задача Вы хотите сохранить объект как часть вашего приложения Flutter. Решение Облачное хранилище — отличное решение для обмена информацией через Интернет. Особенно удобно, что к нему можно получить доступ как к неаутентифицированному источнику (т. е. как к открытому ресурсу). Рассмотрим последовательность действий, необходимую, чтобы обслуживать файл с помощью облачного хранилища: 1. Создайте backet (бакет, корзину) в облачном хранилище у своего облачного провайдера с помощью Cloud Console. 2. Поскольку бакет предназначен для хранения данных, рекомендуется предпочесть местоположение как можно ближе к отправителю запроса. Создание географически распределенного бакета полезно там, где вам нужно обслуживать распределенную аудиторию. 3. Сделайте бакет и его содержимое общедоступными, чтобы к ним можно было получить доступ без необходимости аутентификации. 4. Ограничьте доступ к бакету только чтением, чтобы предотвратить обновление данных внешними источниками. 5. Загрузите тестовый файл, чтобы подтвердить права доступа и доступность бакета через Интернет. 6. Протестируйте доступ с помощью команды curl: curl --request GET [STORAGE_ENDPOINT]/[PATH]/[FILE] Пример приложения Flutter, которое использует удаленный файл JSON, был приведен в Рецепте 13.4. Обсуждение В приведенном примере бакет облачного хранилища играет роль сервера для обслуживания файла. Хранилище объектов представляет собой универсальную технологию, применимую для решения широкого спектра задач. Кроме того, облачное хранилище поддерживает API, который может обеспечить прямой программный доступ к содержимому хранилища. Для начала работы с облачным хранилищем будет полезно понимание названия продукта, предназначенного для хранения информации. В Google Cloud этот тип хранения называется Google Cloud Storage (или GCS). В AWS это будет Simple


Введение в облачные сервисы | 225 Storage Service (или S3). Аналогичное хранилище Azure названо Blob-хранилищем. Каждый из предложенных сервисов обеспечивает безопасное хранение объектов, которое может быть полезно в ряде конкретных случаев. Облачное хранилище целесообразно также в качестве хостингового решения. Вместо того чтобы создавать приложение для обеспечения необходимого взаимодействия с API, вы можете воспользоваться облачным хранилищем, которое предоставляет очень доступное решение без необходимости написания кода программы. Контент, хранящийся в облачном хранилище, также будет содержать метаданные объектов. В этом контексте метаданные представляют пары "ключ/значение", которые браузер задействует при рендеринге содержимого страницы. Для нашего примера с файлом JSON Content-Type имеет значение application/json. Одним из полезных параметров, о котором следует помнить, является Cache-Control, который определяет, как долго объект должен кешироваться. Например, в Google Cloud настройка кеширования находится в разделе метаданных. Чтобы уменьшить срок кеширования для сохраненного общедоступного контента, добавьте параметры public и max-age=15 в раздел Cache-Control страницы метаданных объекта. Имейте в виду, что у облачных провайдеров могут быть заданы разные значения по умолчанию. Длительность кеширования Google Cloud по умолчанию составляет один час (т. е. 3600 секунд). Для AWS этот параметр по умолчанию составляет 24 часа (т. е. 86 400 секунд). Если вы намерены вносить изменения в хранимые объекты во время разработки, то, возможно, захотите сократить продолжительность кеширования до пяти минут (т. е. 300 секунд). При размещении информации в облачном хранилище имеется возможность также управлять информацией при помощи жизненного цикла объекта, следовательно, вы можете автоматически применять события архивирования и удаления в зависимости от некоторого условия. Облачное хранилище может применяться как для краткосрочного, так и долгосрочного хранения. Кроме того, его также можно использовать для статического веб-хостинга и в качестве файловой системы. 16.4. Разработка HTTP-сервера с помощью Dart Задача Вы хотите использовать Dart для разработки HTTP-сервера. Решение Используйте пакет HTTP для создания функциональности HTTP с помощью Dart SDK. На языке Dart можно создавать серверные сервисы для поддержки широкого спектра требований. Вот пример того, как создать базовый HTTP-сервер, который работает с запросами GET и POST. Создайте новое приложение Dart с именем dart_test_http:


226 | Глава 16 import 'dart:convert'; import 'dart:io'; const port = 8080; Future<void> main(List<String> arguments) async { final httpServer = await createHTTPServer(); await httpRequest(httpServer); } Future<HttpServer> createHTTPServer() async { final intAddress = InternetAddress.anyIPv4; return await HttpServer.bind(intAddress, port); } Future<void> httpRequest(HttpServer server) async { await for (HttpRequest request in server) { if (request.method == 'GET'){ request.response ..write(' { "data": [ {"title": "January"}, {"title:": "February"}, {"title": "March"} ] }\n') ..close(); } } } Обсуждение В приведенном примере кода с помощью Dart создается простой сервер, который будет отвечать на HTTP-запросы. Приложение написано на Dart и демонстрирует, как с помощью этого языка создать HTTP-сервер. Протестируйте приложение, а затем подайте команду curl для отправки запроса GET запущенному приложению: curl localhost:8080 Эта команда возвратит строку JSON, подобную показанной в предыдущих главах: { "data": [ {"title": "January"}, {"title:": "February"}, {"title": "March"} ] } Код Dart настроен на прослушивание порта 8080, и после получения запроса он ответит строкой JSON. Из приведенного кода видно, что можно использовать Dart-сервер для обслуживания интерфейсного приложения с помощью JSON (или другого формата). Пример демонстрирует базовый HTTP-сервер и может быть расширен для охвата других запросов, например POST/DELETE/UPDATE.


ПРИЛОЖЕНИЕ Настройка среды разработки Dart — это многофункциональный язык, который обеспечивает разработчика переменными, функциями, методами обработки данных, способами управления потоком и многими другими нужными вещами. Опыт работы с такими языками, как JavaScript, Python и C, означает, что ваш переход на Dart не должен стать трудным. Даже если вы новичок в программировании, я думаю, вы будете приятно удивлены тем, как быстро сможете создать свое первое приложение. Команды разработчиков Dart и Flutter уже выпустили обширную коллекцию учебных пособий. Еще лучше то, что сообщество, работающее в области этих технологий, теперь предоставляет иммерсивные1 решения и демонстрации, чтобы быстрее ввести вас в курс дела. Далее вы узнаете, как установить комплект для разработки программного обеспечения Dart (SDK). Существует несколько вариантов запуска среды Dart, поэтому я расскажу вам о наиболее распространенных (например, с использованием DartPad, Android Studio и VS Code). Определение варианта установки Dart Dart можно запускать непосредственно из браузера в предопределенной среде, такой как DartPad (https://dartpad.dev/). Для опробования языка и начала работы будет достаточно работать с DartPad в браузере. Если вы решили создать скромное приложение, которому не требуются внешние зависимости (например, графика, файлы и т. д.), среда браузера будет соответствовать вашему намерению. Как только вы будете готовы к более сложному сценарию, которому не достаточно библиотек, предоставляемых SDK и доступных в DartPad, вам захочется изучить другие варианты разработки. В качестве альтернативы Dart SDK может быть установлен локально на вашем устройстве, если оно способно его поддерживать. В данном случае необходимо выполнить ряд шагов, прежде чем можно будет приступить к разработке. Если у вас уже есть среда IDE, такая как VS Code или Android Studio, то можно установить плагины для добавления поддержки разработки в Dart и Flutter. 1 Иммерсивный (англ. immersive — присутствие, погружение) — способ восприятия, создающий эффект погружения в искусственно созданную среду. — Пер.


Настройка среды разработки | 261 Здесь мы рассмотрим основные варианты установки, которые помогут вам начать работу. При выборе последующей конфигурации важную роль будут играть ваши личные предпочтения. Использование DartPad Dart предоставляет онлайн-среду для тестирования и запуска кода. DartPad — это отличный онлайн-редактор, с которым можно работать через ваш браузер. При помощи DartPad, вы сможете быстро написать код и поделиться им с выбранной аудиторией, например dart.dev или flutter.dev, через репозиторий Git. Перейдите на DartPad (https://dartpad.dev/) и начните вводить там свой код. DartPad — это действительно мощный инструмент, который вам следует изучить независимо от того, какой тип установки вы выбрали. На рис. П.1 показано, как выглядит простое приложение "Hello, World!" в интерфейсе DartPad. Рис. П.1. Интерфейс DartPad При запуске DartPad открывается новый экземпляр редактора, готовый к работе. Интерфейс представляет собой простую среду разработки с редактором кода, консолью и окнами документации. Редактор кода с левой стороны позволяет вам


Click to View FlipBook Version