- PVSM.RU - https://www.pvsm.ru -
В августе 2018 года Flutter стал самой запрашиваемой кроссплатформенной технологией на Stack Overflow.
В нашем блоге Артем Зайцев, Android-разработчик Surf, и Евгений Сатуров, Android-тимлид Surf, расскажут, почему и как так получилось:
Кроссплатформенные решения давно привлекают желающих быстро и незатратно запустить MVP-продукт одновременно под несколько платформ. Причина проста — единая кодовая база. Ее легче поддерживать: артефакты централизованы, нет дублирования логики и правок одних и тех же багов под каждую из платформ. Да и людей для ее поддержки и создания требуется меньше — нет необходимости содержать двух нативных разработчиков.
Существующие фреймворки либо сложны, либо не слишком производительны в силу нюансов технической реализации, либо полны багов. С их помощью люди стремятся быстро завести минимальную функциональность, а в итоге обрекают себя на переписывание проекта в долгосрочной перспективе.
Совсем скоро ожидается финальный релиз нового фреймворка для мобильной разработки от Google — Flutter, который стал самой запрашиваемой кроссплатформенной технологией на Stack Overflow. Подчеркну, что он предназначен именно для мобильных приложений и охватывает две платформы: Android и iOS. На данный момент представлена Release Preview 2 [1] версия. Новые проекты на Flutter попадают в специальную подборку [2], цель которой — показать возможности фреймворка. Сейчас фреймворк активно пополняется компонентами и архитектурными надстройками благодаря сообществу разработчиков (например, реализация Redux).
Вам не придётся вылезать из привычной Android Studio. При помощи плагина она отлично приспосабливается под разработку Flutter-приложений.
Hot Reload — киллер-фича, позволяющая моментально переносить все изменения из кода на запущенный эмулятор или подключенное устройство.
Если вы когда-либо разрабатывали приложения под Android, уверен, вёрстка — это не то, от чего вы получали удовольствие.
С Flutter всё иначе. Во-первых, никаких XML-файлов с вёрсткой — виджеты создаются и настраиваются прямо в коде (чем-то напоминает Anko Layouts). Вместо View используются Widget.
new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.all(16.0),
child: Text(
'$_name',
),
),
//...
Так выглядит код Flutter-проекта. Поначалу огромное количество скобок пугает, но такие “деревья” довольно наглядны. Flutter пропагандирует композицию: из готовых виджетов можно составить новый, как из конструктора. Почти у любого компонента есть свойство child или children, которое принимает другой элемент или массив элементов соответственно. Все просто и понятно. Сделать красивый пользовательский интерфейс можно достаточно быстро.
Во-вторых, прямо со старта создатели платформы предлагают разработчикам каталог [3] готовых виджетов. Он содержит два набора элементов, Material Components и Cupertino, которые выглядят нативно для каждой из платформ. Кроме того, доступны кроссплатформенные виджеты. Их внешний вид и поведение идентичны на iOS и на Android-устройствах.
Создать красивый и приятный UI в сжатые сроки можно не только благодаря большому количеству готовых виджетов, но и языку, на котором вам придётся писать. Dart [4] отдалённо напоминает Java, JavaScript, C#. Он выразителен и отлично заточен под нужды фреймворка, хотя, после Kotlin некоторые художественные излишества синтаксиса могут ввести в легкий ступор.
Flutter компилируется в нативный код под каждую из платформ. “Под капотом” он использует Skia в качестве графического движка.
Ключевой особенностью архитектуры системы является то, что все виджеты, а также компоненты, ответственные за отрисовку виджетов на канве, являются частью приложения, а не платформы. Именно отсутствие необходимости в переключении контекста и использования "мостов" даёт прирост производительности, который, способствует достижению заветного показателя в 60 FPS при отрисовке UI.
Зачем отказываться от тонны полезного кода, который целое десятилетие создается в сообществе мобильных разработчиков? Все библиотеки, доступные в нативных приложениях SDK и платформенные API могут быть использованы для Flutter-приложений.
Начать работу с Flutter очень просто.
При разработке официальная документация советует использовать Android Studio, IntelliJ или VSCode c соответствующими плагинами, но подойдет любой текстовый редактор.
Скачать архив с Flutter SDK с официального сайта [5] под свою ОС. Распаковать в желаемую директорию и запустить команду flutter doctor
. Данная команда проверит установлено ли все необходимое, а также — наличие плагинов под установленные IDE (например, при установленной Android Studio утилита проверит плагины под нее).
Если все прошло гладко, можно приступать к созданию первого проекта. Если найдены ошибки, doctor подскажет как их решить.
Для использования Flutter в Android Studio необходимо поставить два плагина: Flutter и Dart. Установить их можно стандартным образом, открыв настройки и выбрав нужные плагины в поиске.
Подробно о настройке окружения написано в официальной документации [5].
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
Первое что бросается в глаза при виде Flutter-приложений — непривычный код. В мире Android-разработки используется Java, а с недавнего времени и Kotlin.
Теперь в одном ряду с ними стоит Dart [6]. Google позиционирует его как альтернативу JavaScript со строгой типизацией, высокой производительностью и гибкостью.
Синтаксис Dart прост в освоении, хотя и не так красив как у Kotlin. Возможно, это дело вкуса и привычки.
Проект можно создать, выполнив в консоли команду flutter create name или используя IDE (в Android Studio → New Flutter Project).
После создания проекта вы увидите следующую структуру. В корневой директории приложения есть четыре пакета — lib, ios, android и test.
Первая — директория фреймворка. Там располагаются все dart-файлы и основной код приложения. Несмотря на то, что Flutter компилируется в нативный код, для каждой из платформ приходится писать некоторые нативные взаимодействия. Кроме того, можно встроить Flutter в уже существующее приложение. Для нативного кода предусмотрены два пакета — ios/android, в которых есть возможность писать на привычном для конкретной платформы языке — Obj-C/Swift или Java/Kotlin. В пакете test найдете тесты.
В корневой директории есть файл конфигурации pubspec.yaml — там подключаются библиотеки и т.д. Если говорить об аналогии, то для Flutter’а это, как build.gradle (он тоже есть, но уже в нативной Android части).
Пакет lib можно разбивать на дополнительные пакеты — тут уже дело вкуса и желания использовать ту или иную архитектуру. К слову, для создания приложения на Flutter используются различные приемы, которые можно посмотреть здесь [7].
В вашем проекте сразу будет файл main.dart, содержащий код с примером. У приложения единая точка входа — метод main. Он отвечает за создание корневого виджета.
Все, что вы видите (или не видите) на экране, все, с чем происходит взаимодействие и само приложение — виджеты. Любая сущность пользовательского интерфейса — виджет. Текстовое поле, отступ или детектор жестов — виджеты. Приложение построено из них, как конструктор.
Согласно официальному сайту, “каждый виджет является неизменяемым описанием части пользовательского интерфейса”.
Для примера построим приложение с таким экраном:
Здесь присутствуют следующие виджеты:
Часть из них реализована в фреймворке, часть необходимо составить самим из готовых деталей.
Виджеты бывают двух типов Stateless
и Stateful
. Первые статичны (например, текст), вторые поддерживают изменение состояния (например, экран).
Примером такого виджета в приложении может быть MyApp. Это корень приложения. Внутри разместим все, что требуется для отрисовки с помощью метода build.
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: new AppBar(
title: new Text("Flutter Random Name"),
),
body: new MyHomePage(),
),
);
}
}
Любой статичный виджет — наследник класса StatelessWidget
. Вам всего лишь необходимо переопределить метод build, а в нем собрать необходимый элемент. Flutter пропагандирует композицию. Для создания нового элемента не следует расширять уже существующий.
В примере данный виджет строится из MaterialApp
(корень приложения, основанного на компонентах из MaterialDesign), внутри которого лежит Scaffold
— это экран.
MyHomePage
— тоже виджет, который отрисовывает тело экрана, исключая AppBar
. В данном случае он имеет состояние. О нем поговорим ниже.
Построение интерфейса происходит через передачу конструктора класса в соответствующее поле с инициализацией аргументов. Dart поддерживает опциональные параметры методов, благодаря этому достигается гибкость в создании UI.
Замечание: слово new
в Dart, начиная со второй версии, опционально.
Такой вот компоновкой виджетов можно получить статичный экран приложения. Причем фантазия разработчика неограничена вообще ничем.
Виджеты с состоянием поддерживают перерисовку при изменении их состояния (State
). Чтобы сделать такой виджет необходимо наследоваться от StatefullWidget
и создать класс-наследник State<T>
, который является состоянием виджета и отвечает за то, что пользователь увидит на экране смартфона.
Изменение состояния виджета происходит через вызов метода setState() {}
. Внутри можно, например, задать другой цвет фона кнопки, и фреймворк сам определит минимально необходимую перерисовку UI.
В моем случае главная страница MyHomePage
будет виджетом с состоянием. Оно хранит _name
— имя, которое будет выводится в текстовом блоке, и флаг загрузки _isLoading
(отвечает за то, как будет отрисован внутренний виджет LoadingButton
; пример управления состоянием через родителя).
class _MyHomePageState extends State<MyHomePage> {
String _name = "";
bool _isLoading = false;
@override
Widget build(BuildContext context) => Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.all(16.0),
child: Text(
'$_name',
),
),
LoadingButton(
isLoading: _isLoading,
action: _generateName,
)
],
),
);
}
У кнопки есть коллбек, action
, куда подается метод _generateName()
. Замечу, что в Dart нет модификаторов доступа, типа private
и public
. Но если необходимо сделать приватным что-либо внутри модуля, то наименование должно начинаться с префикса “_”.
Метод _generateName
асинхронный. Он отвечает за загрузку имени, изменяет флаг isLoading
и устанавливает значение name
, что приводит к перерисовке кнопки и текста.
final snack = SnackBar(content: Text("Handle error!"));
_generateName() async {
toggleLoading();
try {
//загрузка данных через await
//парсинг Json
setName(map["name"]);
toggleLoading();
} catch (e) {
setName("oops!");
Scaffold.of(context).showSnackBar(snack);
toggleLoading();
}
}
void toggleLoading() {
setState(() {
_isLoading = !_isLoading;
});
}
Для изменения состояния обязательно нужно вызвать setState() {}
. Без этого вызова виджет просто не будет перерисован.
Реализация лоадера оказалась довольно простой. В момент перерисовки подставляется либо текст, либо индикатор в кнопку.
Реализация занимает всего несколько строк
_buildButtonChild() {
if (isLoading) {
return Transform.scale(
scale: 0.5,
child: CircularProgressIndicator(),
);
} else {
return Text("Click for name");
}
}
Transform.scale
нужен, чтобы уменьшить размер.
Асинхронное взаимодействие в Flutter, собственно как и в Dart, основано на async-await
. Подробнее можно посмотреть здесь [8], здесь [9] и здесь [10].
Сегодня, когда новые материалы по Flutter выходят едва ли не ежедневно, нет никакого дефицита в хороших курсах, помогающих подружиться с данной технологией.
Хороший пример базового курса по Flutter — курс на Udacity [11]. Уроки разбиты на две главы, вдумчивое прохождение каждой из которых займёт 3-4 часа.
Если же курсы не ваш вариант, начните погружение в технологию через изучение исходников уже существующих проектов. Репозиторий awesome-flutter [12] содержит немало таких проектов, а еще может похвастаться очень щедрой подборкой готовых библиотек, решений, сэмплов и прочих материалов для изучения и вдохновения.
По результатам более глубокого погружения в тему, от былого скептицизма у нас не осталось и следа. Flutter не похож на эксперимент, а скорее показывает направление, в котором в ближайшие годы будет двигаться весомая часть индустрии мобильной разработки. Несколько смелых концепций, лежащих в основе Flutter, привносят в разработку новые идеи и возможности. Быстрое, почти интуитивное создание пользовательского интерфейса делает прототипирование и UX-эксперименты простыми как никогда и доступными каждому. В какой сфере Flutter найдёт своё применение — покажет время.
Автор: saturovv
Источник [13]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/mobil-naya-razrabotka/296177
Ссылки в тексте:
[1] Release Preview 2: https://flutter.io/
[2] подборку: https://flutter.io/showcase/
[3] каталог: https://flutter.io/widgets/
[4] Dart: https://www.dartlang.org/
[5] официального сайта: https://flutter.io/get-started/install/
[6] Dart: https://www.dartlang.org/guides/language
[7] здесь: https://github.com/brianegan/flutter_architecture_samples/blob/master/example/
[8] здесь: https://www.dartlang.org/tutorials/language/futures
[9] здесь: https://flutter.io/cookbook/networking/fetch-data/
[10] здесь: https://medium.com/@takahirom/how-to-write-flutter-asynchronous-processing-22f845204f30
[11] Udacity: https://classroom.udacity.com/courses/ud905
[12] awesome-flutter: https://github.com/Solido/awesome-flutter
[13] Источник: https://habr.com/post/426701/?utm_source=habrahabr&utm_medium=rss&utm_campaign=426701
Нажмите здесь для печати.