Flutter — новый взгляд на кроссплатформенную разработку

в 10:10, , рубрики: flutter, Блог компании Google, дизайн мобильных приложений, кроссплатформенная разработка, мобильная разработка, разработка мобильных приложений

В августе 2018 года Flutter стал самой запрашиваемой кроссплатформенной технологией на Stack Overflow.

image

В нашем блоге Артем Зайцев, Android-разработчик Surf, и Евгений Сатуров, Android-тимлид Surf, расскажут, почему и как так получилось:

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

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

Совсем скоро ожидается финальный релиз нового фреймворка для мобильной разработки от Google — Flutter, который стал самой запрашиваемой кроссплатформенной технологией на Stack Overflow. Подчеркну, что он предназначен именно для мобильных приложений и охватывает две платформы: Android и iOS. На данный момент представлена Release Preview 2 версия. Новые проекты на Flutter попадают в специальную подборку, цель которой — показать возможности фреймворка. Сейчас фреймворк активно пополняется компонентами и архитектурными надстройками благодаря сообществу разработчиков (например, реализация Redux).

Flutter — новый взгляд на кроссплатформенную разработку - 2

Почему нужно поверить во Flutter?

Отличный тулинг для быстрой разработки

Вам не придётся вылезать из привычной Android Studio. При помощи плагина она отлично приспосабливается под разработку Flutter-приложений.

Hot Reload — киллер-фича, позволяющая моментально переносить все изменения из кода на запущенный эмулятор или подключенное устройство.

Flutter — новый взгляд на кроссплатформенную разработку - 3

Простота и выразительность вёрстки

Если вы когда-либо разрабатывали приложения под 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, которое принимает другой элемент или массив элементов соответственно. Все просто и понятно. Сделать красивый пользовательский интерфейс можно достаточно быстро.

Во-вторых, прямо со старта создатели платформы предлагают разработчикам каталог готовых виджетов. Он содержит два набора элементов, Material Components и Cupertino, которые выглядят нативно для каждой из платформ. Кроме того, доступны кроссплатформенные виджеты. Их внешний вид и поведение идентичны на iOS и на Android-устройствах.

Flutter — новый взгляд на кроссплатформенную разработку - 4

Реактивный фреймворк

Создать красивый и приятный UI в сжатые сроки можно не только благодаря большому количеству готовых виджетов, но и языку, на котором вам придётся писать. Dart отдалённо напоминает Java, JavaScript, C#. Он выразителен и отлично заточен под нужды фреймворка, хотя, после Kotlin некоторые художественные излишества синтаксиса могут ввести в легкий ступор.

Flutter компилируется в нативный код под каждую из платформ. “Под капотом” он использует Skia в качестве графического движка.

Flutter — новый взгляд на кроссплатформенную разработку - 5

Ключевой особенностью архитектуры системы является то, что все виджеты, а также компоненты, ответственные за отрисовку виджетов на канве, являются частью приложения, а не платформы. Именно отсутствие необходимости в переключении контекста и использования "мостов" даёт прирост производительности, который, способствует достижению заветного показателя в 60 FPS при отрисовке UI.

Вся мощь платформы по-прежнему в ваших руках

Зачем отказываться от тонны полезного кода, который целое десятилетие создается в сообществе мобильных разработчиков? Все библиотеки, доступные в нативных приложениях SDK и платформенные API могут быть использованы для Flutter-приложений.

Flutter — новый взгляд на кроссплатформенную разработку - 6

Настройка окружения

Начать работу с Flutter очень просто.

При разработке официальная документация советует использовать Android Studio, IntelliJ или VSCode c соответствующими плагинами, но подойдет любой текстовый редактор.

Шаг первый

Скачать архив с Flutter SDK с официального сайта под свою ОС. Распаковать в желаемую директорию и запустить команду flutter doctor. Данная команда проверит установлено ли все необходимое, а также — наличие плагинов под установленные IDE (например, при установленной Android Studio утилита проверит плагины под нее).

Шаг второй

Если все прошло гладко, можно приступать к созданию первого проекта. Если найдены ошибки, doctor подскажет как их решить.

Шаг третий

Для использования Flutter в Android Studio необходимо поставить два плагина: Flutter и Dart. Установить их можно стандартным образом, открыв настройки и выбрав нужные плагины в поиске.

Подробно о настройке окружения написано в официальной документации.

Dart

import  'package:flutter/material.dart';  

void main() => runApp(MyApp());

Первое что бросается в глаза при виде Flutter-приложений — непривычный код. В мире Android-разработки используется Java, а с недавнего времени и Kotlin.

Теперь в одном ряду с ними стоит Dart. Google позиционирует его как альтернативу JavaScript со строгой типизацией, высокой производительностью и гибкостью.

Синтаксис Dart прост в освоении, хотя и не так красив как у Kotlin. Возможно, это дело вкуса и привычки.

Создание проекта

Проект можно создать, выполнив в консоли команду flutter create name или используя IDE (в Android Studio → New Flutter Project).

Структура приложения

После создания проекта вы увидите следующую структуру. В корневой директории приложения есть четыре пакета — lib, ios, android и test.

Flutter — новый взгляд на кроссплатформенную разработку - 7

Первая — директория фреймворка. Там располагаются все dart-файлы и основной код приложения. Несмотря на то, что Flutter компилируется в нативный код, для каждой из платформ приходится писать некоторые нативные взаимодействия. Кроме того, можно встроить Flutter в уже существующее приложение. Для нативного кода предусмотрены два пакета — ios/android, в которых есть возможность писать на привычном для конкретной платформы языке — Obj-C/Swift или Java/Kotlin. В пакете test найдете тесты.

В корневой директории есть файл конфигурации pubspec.yaml — там подключаются библиотеки и т.д. Если говорить об аналогии, то для Flutter’а это, как build.gradle (он тоже есть, но уже в нативной Android части).

Пакет lib можно разбивать на дополнительные пакеты — тут уже дело вкуса и желания использовать ту или иную архитектуру. К слову, для создания приложения на Flutter используются различные приемы, которые можно посмотреть здесь.

В вашем проекте сразу будет файл main.dart, содержащий код с примером. У приложения единая точка входа — метод main. Он отвечает за создание корневого виджета.

Everything is a Widget

Все, что вы видите (или не видите) на экране, все, с чем происходит взаимодействие и само приложение — виджеты. Любая сущность пользовательского интерфейса — виджет. Текстовое поле, отступ или детектор жестов — виджеты. Приложение построено из них, как конструктор.

Согласно официальному сайту, “каждый виджет является неизменяемым описанием части пользовательского интерфейса”.

Для примера построим приложение с таким экраном:

Flutter — новый взгляд на кроссплатформенную разработку - 8Flutter — новый взгляд на кроссплатформенную разработку - 9

Здесь присутствуют следующие виджеты:

  • приложение
  • экран
  • AppBar
  • текст
  • кнопка с лоадером

Часть из них реализована в фреймворке, часть необходимо составить самим из готовых деталей.

Виджеты бывают двух типов Stateless и Stateful. Первые статичны (например, текст), вторые поддерживают изменение состояния (например, экран).

Stateless

Примером такого виджета в приложении может быть 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, начиная со второй версии, опционально.

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

Statefull

Виджеты с состоянием поддерживают перерисовку при изменении их состояния (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() {}. Без этого вызова виджет просто не будет перерисован.

Реализация лоадера оказалась довольно простой. В момент перерисовки подставляется либо текст, либо индикатор в кнопку.

Flutter — новый взгляд на кроссплатформенную разработку - 10

Реализация занимает всего несколько строк

_buildButtonChild() {  
  if (isLoading) {  
    return Transform.scale(  
      scale: 0.5,  
      child: CircularProgressIndicator(),  
    );  
  } else {  
    return Text("Click for name");  
  }  
}

Transform.scale нужен, чтобы уменьшить размер.

Асинхронное взаимодействие в Flutter, собственно как и в Dart, основано на async-await. Подробнее можно посмотреть здесь, здесь и здесь.

С чего начать?

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

Хороший пример базового курса по Flutter — курс на Udacity. Уроки разбиты на две главы, вдумчивое прохождение каждой из которых займёт 3-4 часа.

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

Заключение

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

Автор: saturovv

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js