[Перевод] Flutter и настольные приложения

Ни для кого не секрет то, что команда разработчиков Flutter стремится к тому, чтобы этот фреймворк позволял бы, пользуясь единой кодовой базой, создавать приложения для широкого разнообразия платформ. Сюда входят iOS, Android, Windows, Linux, macOS и веб. При этом такие приложения должны компилироваться в формат, специфичный для каждой из платформ, а их внешний вид не должен уступать внешнему виду хорошо сделанных игр. В Google фреймворк Flutter применяется во многих проектах: от Assistant до Stadia, от Cloud Search до Blogger. Flutter используются и другими компаниями — от ByteDance до Grab, от Nubank до MGM Resorts. Всем им приносит пользу та гибкость и продуктивность разработки, которую даёт Flutter.

Многие из вас заинтересованы в развитии возможностей Flutter, касающихся настольных платформ, куда входят Windows, macOS, Linux. В опросах и на GitHub тема разработки настольных приложений относится к одной из самых заметных новых возможностей Flutter. В ближайшее время мы собираемся больше рассказать о том, чем мы занимаемся. Полагаем, стоит начать с обзора того, что сделано различными командами, отвечающими за возможности Flutter. Хотя поддержка настольных приложений пока находится на стадии ознакомительной технической версии, над соответствующими возможностями ведётся серьёзная работа.

7c20b459f7369dc3bdcbcbed8bed15fe.png


Сборка приложений


Недавно мы выпустили профили и режимы сборки приложений для Windows и Linux — в дополнение к существующей поддержке macOS. Например, если вы пользуетесь последней сборкой Flutter, Flutter-приложения можно компилировать в исполняемые файлы Windows командой flutter build windows. Для этого используется наш AOT-компилятор продакшн-уровня, который позволяет создавать машинный код для архитектуры x64, который можно выполнять на соответствующих компьютерах без установки Flutter.

Особенности настольных приложений


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

Мы, на уровне фреймворка, внесли во Flutter некоторые изменения, которые направлены на поддержку настольных приложений.

  • Когда вы создаёте новый проект в свежих сборках Flutter, вы увидите, что шаблон, применяемый по умолчанию, теперь включает в себя ссылку на свойство visualDensity, которое позволяет настраивать визуальную плотность расположения элементов управления на основе целевой платформы приложения. В макетах настольных приложений элементы управления «упакованы» плотнее, чем в мобильных приложениях. Например, это используется при настройке текстового поля (TextField), которое теперь предлагает варианты визуальной плотности compact, comfortable и standard, зависящие от параметров проекта.
  • Мы значительно улучшили поддержку мыши и клавиатуры. Сюда входит возможность работы с кодами клавиш клавиатуры в Windows, поддержка щелчка правой кнопкой мыши, поддержка изменения курсора и колёсика мыши.
  • Теперь можно, пользуясь классом Platform, узнавать о том, на какой платформе выполняется приложение. При работе приложения, а Windows, macOS и Linux можно получить соответствующие результаты.
  • В самом свежем релизе мы добавили виджет NavigationRail, представляющий нечто вроде боковой панели. Этот виджет специально спроектирован для поддержки возможностей приложений, запускаемых на настольных ПК и на планшетах.


FFI


Команда Dart проделала большую работу по улучшению интерфейса внешних функций (Foreign Function Interface, FFI). Это способствует повышению скорости внедрения новых возможностей во Flutter. Например, для API, основанных на C, библиотека dart:ffi предоставляет прямой механизм для организации привязки к нативному коду. Среда выполнения Dart даёт возможность вызывать динамически связываемые библиотеки и выделять память в куче. В основе этого механизма лежат объекты Dart.

Вот фрагмент кода (здесь можно найти его полный вариант), представляющий собой простой пример, в котором показано обращение к традиционному Win32-API MessageBox(), полностью выполняемое средствами Dart-кода:

typedef MessageBoxNative = Int32 Function(
    IntPtr hWnd, Pointer lpText, Pointer lpCaption, Int32 uType);
typedef MessageBoxDart = int Function(
    int hWnd, Pointer lpText, Pointer lpCaption, int uType);

final user32 = DynamicLibrary.open('user32.dll');
final win32MessageBox =
    user32.lookupFunction('MessageBoxW');

void showMessageBox(String message, String caption) => win32MessageBox(
    0,                      // Нет окна-владельца
    Utf16.toUtf16(message), // Текст сообщения
    Utf16.toUtf16(caption), // Заголовок окна
    0                       // Только кнопка OK
    );

…

showMessageBox('Test Message', 'Window Caption'); // этот вызов выглядит как вызов обычной Dart-функции


Здесь у нас имеются typedef-псевдонимы, представляющие сигнатуры методов и для их нативного представления, и для их Dart-представления. Когда у нас есть эти псевдонимы, мы можем загрузить динамически связываемую библиотеку Windows, которая содержит реализацию функции. Для этого можно воспользоваться методом lookupFunction(), который делает мэппинг сигнатуры функции Dart на нативную функцию. И, наконец, мы, что не обязательно, описываем простую функциональную обёртку, которая упрощает работу с нативными механизмами в Dart-коде. В результате у нас получается нечто, подобное следующему рисунку.

bf70f4afc2bf517b2af0fcff2b296ad5.png


Простой пример Windows-проекта, в котором использовано Win32-API MessageBox ()

На самом деле, программисту необязательно делать всё это самому. Дело в том, что велика вероятность того, что кто-то уже подготовил код, упрощающий работу с необходимыми вам API. Здесь о FFI можно почитать подробнее.

Обновление модели плагинов


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

Правда, учитывая то, что во Flutter улучшается поддержка мобильных и настольных платформ, а так же веб-приложений, разрабатывать плагины для каждой поддерживаемой фреймворком платформы становится всё сложнее и сложнее. При разработке некоего плагина, весьма вероятно, понадобится объединить усилия разных программистов, каждый из которых хорошо разбирается в какой-то платформе.

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

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

Обратите внимание на то, что API плагинов для Windows и Linux пока ещё не устоялся, поэтому, хотя мы и советуем разработчикам знакомиться с новыми возможностями Flutter, мы пока не готовы к выпуску этих возможностей в продакшн. Мы, кроме того, работаем над добавлением на pub.dev тегов, относящихся к настольным платформам.

Запуск программ на Windows: Win32 и UWP


Один интересный аспект нашей работы, связанный с Windows, заключается в том, что здесь мы экспериментируем с различными подходами к архитектуре. Flutter, на любой платформе, внедряется в маленькое хост-приложение, являющееся контейнером («embedder») с применением подхода, напоминающего тот, который используется в игровых движках вроде Unity. Это приложение-embedder, особое для каждой платформы, предоставляет нам точку входа в проект. Оно согласовывает свои действия с операционной системой, работая со средствами рендеринга, с пользовательским вводом и с инструментами, обеспечивающими доступность контента. Оно поддерживает и цикл событий.

010e76244e50a016bff0ee87ffc533a0.png


Windows даёт нам два способа создания подобного приложения. Первый — это зрелая модель программирования Win32, которую можно использовать в качестве точки входа для Flutter-проектов. Этот подход предлагает максимальный уровень обратной совместимости с различными платформами, с такими, как Windows 7. Он позволяет создавать стандартные EXE-файлы, которые ожидает получить в результате работы над проектом множество программистов. В отличие от Win32, современная модель приложений UWP рекомендована для Windows 10. Эта модель предлагает заманчивые возможности по созданию Flutter-приложений для особых устройств, вроде Xbox, и для ОС Windows 10X, которая должна скоро выйти.

Мы, неофициально, работаем с различными разработчиками и исследуем разные решения. Мы с удовольствием более близко поработали бы с Microsoft ради того, чтобы повысить качество Windows-приложений, сделанных во Flutter. Так как семейство устройств Surface теперь включает в себя системы, основанные на Android и на Windows, мы думаем, что Flutter способен предложить Microsoft мощную платформу, которая позволяет создавать привлекательные нативные приложения для самых разных устройств.

Эксперименты с настольными приложениями


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

Если вы уже сейчас хотите испытать новые возможности, то вам нужно пользоваться каналом разработки. Поддержка Windows и Linux доступна в ветке master, в том месте, где идёт активная разработка Flutter. Поддержка macOS доступна в ветке dev. Там находятся более стабильные возможности, которые, правда, не рекомендуется применять в продакшне. Переключаться между каналами можно, используя команды flutter channel master или flutter channel dev. После этого нужно выполнить одну из следующих команд для того чтобы включить поддержку интересующей вас платформы:

C:\flutter> flutter config --enable-windows-desktop
$ flutter config --enable-macos-desktop
$ flutter config --enable-linux-desktop


Мы уже видели, как некоторые смелые разработчики начали создавать настольные приложения с помощью новых возможностей Flutter. Одно из первых таких приложений разработано для macOS. Оно называется Sharezone. Это — планировщик для учеников, нацеленный на немецкий рынок образования. Сначала этот проект был выпущен в виде мобильного приложения. А недавно он вышел в настольном варианте и в варианте, предназначенном для веб.

3b6390743f25463268afb7594fafa25d.png


Sharezone Schulplan — приложение для учеников, учителей и родителей. Оно позволяет планировать и отслеживать домашние задания, учебные группы и расписания

Планируете ли вы использовать Flutter для разработки настольных приложений?

guabcgmwuqoopx1ar80sjpz6keq.png

de0yl-6ppopvisr_a80b4yuhjj8.png

© Habrahabr.ru