Повышение производительности, новые фичи Firebase, состояние десктопной версии, новые инструменты и многое другое.

Я — Евгений Сатуров, Head of Flutter в Surf и ведущий Flutter Dev Podcast. Представляю перевод официальной статьи про свежий релиз Flutter 2.8, дополненный моими комментариями.

Вот в северное полушарие и пришла та самая пора: листва опадает, на улице холодает, и последний стабильный релиз этого года уже тут как тут. Всем привет и добро пожаловать во Flutter 2.8! Этот релиз стал результатом труда 207 контрибьюторов и 178 рецензентов, которым удалось смёрджить 2 424 PR и решить 2976 проблемных моментов. 

Благодаря коллективной работе контрибьюторов:

  • существенно улучшилась производительность движка и Flutter DevTools, 

  • вышел стабильный релиз Google Mobile Ads SDK для Flutter, 

  • появилась целая гора новых фич и усовершенствований Firebase, WebView 3.0, 

  • добавилась новая партия пакетов Flutter Favorite, 

  • много обновлений для десктопа уже на пути к стабильному релизу.

В довесок к ним вышла новая версия DartPad, которая теперь поддерживает ещё больше пакетов, включая Firebase. Может, это и последний релиз года, но точно не по значимости. Погнали разбираться!

Производительность

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

Запуск

Улучшения коснулись задержки запуска. Их мы протестировали на Google Pay — огромном и крайне популярном приложении, в котором более одного миллиона строк кода. Последние улучшения помогли сократить задержку при запуске Google Pay на 50% на слабых Android-устройствах и на 10% — на мощных.

Мы ослабили влияние Flutter на политику сборки мусора Dart VM: это помогло избежать несвоевременного запуска циклов сбора при запуске приложения. К примеру, теперь перед рендерингом первого кадра на Android Flutter уведомляет Dart VM только о сигналах нехватки памяти уровня TRIM_LEVEL_RUNNING_CRITICAL и выше. При локальном тестировании это изменение в некоторых случаях сократило время отрисовки первого кадра на слабых устройствах на целых 300 мс.

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

Раньше запуск дефолтного менеджера шрифтов вызывал искусственную задержку при запуске первого Dart-изолята. Мы сократили задержку: отложили запуск дефолтного менеджера шрифтов, чтобы он происходил одновременно с запуском Isolate в Dart.

Комментарий Евгения Сатурова

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

Память

Flutter-разработчики, занимавшиеся устройствами с ограниченной памятью, столкнулись с проблемой при трассировке производительности. Flutter бросался загружать «сервисный изолят» Dart VM: AOT-код связывался с приложением таким образом, что Flutter считывал их в память одновременно. 

Для Android в релизе 2.8 мы выделили сервисному изоляту Dart VM свой собственный bundle, который можно загружать отдельно. Благодаря этому в приложении удаётся сэкономить до 40 мб памяти — пока не потребуется использовать сервисный изолят.

Кроме того, мы сократили объём требуемой памяти на 10%: научили Dart VM сообщать ОС, что страницы памяти, используемые AOT-программой, содержат сохранённую в файл информацию. Она, скорее всего, больше не будет считываться в память. В результате страницы, которые были заняты копией данных, можно очистить и переиспользовать.

Профилирование

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

В стабильном релизе 2.8 события трассировки отправляются в регистратор системной трассировки Android, если его активировали при запуске приложения. Более того, события отправляются, даже если это релизная сборка Flutter-приложения.

События трассировки во Flutter теперь отображаются (снизу) в инструментах регистрации системной трассировки для Android

Комментарий Евгения Сатурова

Наши разработчики, которые раньше писали под Android, пожалуй, больше всего скучают по нативному профайлеру, которым может похвастаться Android Studio. Это действительно мощный инструмент, который… совершено бесполезен во Flutter-разработке. Был. До выхода 2.8. Примечательно, что параллельно с развитием своей экосистемы инструментов, Flutter не забывает встраиваться и в инструменты родственных платформ.

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

Flutter DevTools

Для отладки проблем с производительностью в этом релизе DevTools мы добавили новую фичу расширенной трассировки «Enhance Tracing». С её помощью можно диагностировать причины лагов UI: ресурсозатратные сборки, вёрстку и отрисовку объектов.

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

В этом релизе DevTools добавились новые возможности профилирования производительности при запуске приложения. Новая статистика содержит анализ нагрузки ЦП: начиная с инициализации Dart VM и заканчивая рендерингом первого кадра на Flutter. Как только вы нажмёте кнопку «Profile app start up» («Профилировать запуск приложения») и статистика по запуску приложения загрузится, программа выберет для неё тег «AppStartUp» («Запуск приложения»). Профилирование загрузки приложения также можно запустить, выбрав сам тег (если он есть) из списка доступных пользовательских тегов. Так вы получите доступ к данным профилирования при запуске приложения.

Платформенные view из веба

Android и iOS — не единственные платформы, которым достанутся обновления, повышающие производительность. В этом релизе мы также улучшили производительность платформенных view для Flutter web. 

С помощью платформенных view можно размещать в приложении компоненты нативного UI из платформы используемого вами устройства. Flutter web позволяет поместить HTML элементы в веб-приложение на Flutter с помощью виджета HtmlElementView. Если вы пользуетесь веб-версиями плагина google_maps_flutter, плагина video_player или следуете рекомендациям команды Flutter об оптимизации отображения картинок в веб, вы пользуетесь платформенными view.

Чтобы встроить платформенные view, в прошлых версиях Flutter приходилось создавать новый холст каждый раз. Чем больше платформенных view, тем больше холстов. Каждый новый холст требует очень много ресурсов, так как занимает всё окно целиком. В этом релизе Flutter переиспользует холсты, созданные для предыдущих view. В результате, вместо того, чтобы тратить в 60 раз больше ресурсов каждую секунду, приложение требует их один раз за время работы. Можно добавлять в веб-приложение несколько экземпляров HtmlElementView: это не снизит производительность и уменьшит лаги при скроллинге страницы с платформенными view.

Комментарий Евгения Сатурова

Flutter for Web — это пока не наша история. Мы подходим к выбору технолгий для нашего стека очень аккуратно. Хотя по нам и не скажешь: кто ещё писал на Flutter уже в начале 2019 года? А мы писали.

Но в случае с Flutter for Web — это другое. Имеющиеся сейчас проблемы с поддержкой фреймворком веб-платформы уходят довольно глубоко в фундаментальные принципы, на которых он основан. Можно дошлифовать производительность и UX, а вот что делать с адаптацией к SEO и оптимизацией скорости загрузки приложения, пока непонятно.

А вот оптимизация платформенных компонентов для веба — это отлично. Но это капля в море.

Экосистема

Flutter — это не просто фреймворк, движок и инструменты. На pub.dev представлено более 20 тысяч совместимых с Flutter пакетов и плагинов, и каждый день их количество растёт. То, с чем Flutter разработчики взаимодействуют ежедневно, – лишь верхушка огромной экосистемы. Давайте посмотрим, что нового успело произойти в экосистеме Flutter с предыдущего релиза.

Flutter Ads в общем доступе

Начнём с релиза Google Mobile SDK для Flutter в общий доступ в ноябре.

Баннерная реклама | Полноэкранная реклама | Видеореклама с вознаграждением | Нативная реклама | Реклама при запуске приложения

Google Mobile Ads SDK для Flutter
Баннерная реклама | Полноэкранная реклама | Видеореклама с вознаграждением | Нативная реклама | Реклама при запуске приложения Google Mobile Ads SDK для Flutter

Релиз поддерживает пять форматов рекламы, интеграцию с AdMob и Ad Manager и включает бета-версию новой фичи для размещения рекламы от посредников. С её помощью можно оптимизировать производительность приложения. Более подробно об интеграции Google Рекламы во Flutter-приложение и других способах монетизации рассказываем на новой страничке о монетизации на flutter.dev.

WebView 3.0

Ещё один новый релиз, вышедший в этот раз вместе с Flutter, — версия 3.0 плагина webview_flutter. Мы подняли номер версии: в ней добавилось много новых фич, а ещё она, скорее всего, существенным образом изменит принцип работы webview на Android.

В предыдущих версиях webview_flutter режим гибридной компоновки («Hybrid Composition») уже был доступен, но не по умолчанию. Гибридная компоновка решает ряд проблем, существовавших в предыдущем дефолтном режиме «Virtual Display». Учитывая отзывы пользователей и статистику багов, мы решили, что пришло время сделать гибридную компоновку дефолтной. Кроме того, с webview_flutter добавилось несколько фич, о которых многие просили:

  • Поддержка POST и GET для наполнения контентом (4450, 4479, 4480, 4573)

  • Загрузка HTML из файлов и строк с текстовой информацией (4446, 4486, 4544, 4558)

  • Поддержка прозрачного фона (3431, 4569, 4570)

  • Запись информации в cookies до загрузки контента (4555, 4556, 4557)

Помимо этого, в релизе webview_flutter 3.0 добавилась пробная поддержка новой платформы — веб. Многие из вас просили о возможности размещать webview в веб-приложении на Flutter, с помощью которого можно собрать мобильное или веб-приложение на единой кодовой базе. Как выглядит webview в веб-приложении на Flutter? С точки зрения кода — как обычно:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_web/webview_flutter_web.dart';

void main() {
  runApp(const MaterialApp(home: HomePage()));
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    super.initState();

    // required while web support is in preview
    if (kIsWeb) WebView.platform = WebWebViewPlatform();
  }

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(title: const Text('Flutter WebView example')),
        body: const WebView(initialUrl: 'https://flutter.dev'),
      );
}

При запуске в веб работает так, как и ожидается:

Следует заметить, что у текущей реализации webview_flutter для веб есть ряд ограничений. Она написана с помощью iframe: он поддерживает только загрузку простых URL и не умеет контролировать или взаимодействовать с загруженным контентом (подробнее читайте в the webview_flutter_web README). Однако по просьбе сообщества мы предоставляем доступ к webview_flutter_web в виде неофициального плагина. Если хотите его попробовать, добавьте следующую строку к pubspec.yaml:

dependencies:
  webview_flutter: ^3.0.0
  webview_flutter_web: ^0.1.0 # add unendorsed plugin explicitly

Если у вас возникла проблема с webview_flutter v3.0, пишите во Flutter репозиторий с пометкой «webview issue». Если же вы ещё не пользовались webview, прочтите новый codelab по webview, в котором пошагово расписан процесс внедрения веб-контента в приложении на Flutter.

Flutter Favorites

Комитет по экосистеме Flutter провёл очередную встречу и включил следующие пакеты во Flutter Favorite:

  • Три кастомных пакета маршрутизации для нового Router API: beamer, routemaster и go_router.

  • drift — получившая новое имя функциональная и популярная реактивная библиотека для управления базами данных во Flutter и Dart, созданная на основе sqlite.

  • freezed — «языковой патч» для Dart, содержащий простой синтаксис для описания моделей, клонирования объектов, поиска по шаблону и других действий.

  • dart_code_metrics.

  • Несколько красивых пакетов для графического интерфейса: flex_color_scheme, flutter_svg, feedback, toggle_switch и auto_size_text.

Любимый пакет Flutter можно выдвинуть на премию Flutter Favorite. Руководство и инструкции — на странице программы «Flutter Favorite».

Комментарий Евгения Сатурова

Попадание пакета в программу сертификации Flutter Favorite — большое событие. На данный момент таких пакетов всего 64 (из 22 тысяч, доступных на pub.dev). Лычка Flutter Favorite — это безоговорочное признание ценности и качества пакета сообществом и создателями самого фреймворка.

Тем радостнее мне наблюдать dart_code_metrics среди пакетов, наконец получивших этот почётный статус. dart_code_metrics был создан бывшим членом нашей дружной команды (привет, Дима!). А наш Flutter-разработчик Влад Коношенко активно контрибьютит в dart_code_metrics и по сей день.

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

Платформо-специфичные пакеты

Если вы создаёте пакет, вам необходимо решить, какие платформы поддерживать. Если плагин содержит платформо-специфичный нативный код, это можно сделать с помощью свойства pluginClass в pubspec.yaml проекта, где указывается нативный класс, обеспечивающий выполнение фичи:

flutter:
  plugin:
    platforms:
      android:
        package: com.example.hello
        pluginClass: HelloPlugin
      ios:
        pluginClass: HelloPlugin

Однако Dart FFI не стоит на месте: сейчас можно внедрить платформо-специфичную функциональность с помощью кода, на 100% состоящего из Dart, как сделали с пакетом path_provider_windows. Даже если пакет не имеет нативных классов, вы всё ещё можете указать, что он поддерживает определённую платформу. В таком случае используйте свойство dartPluginClass:

flutter:
  plugin:
    implements: hello
    platforms:
      windows:
        dartPluginClass: HelloPluginWindows

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

Firebase

Ещё одна важная часть экосистемы Flutter — это FlutterFire. В этом релизе мы добавили ряд новых фич, благодаря которым писать приложения с помощью Flutter и Firebase станет проще:

  • Все плагины FlutterFire переходят из беты в стабильный канал.

  • Поддержка нескольких сервисов Firebase в DartPad.

  • Новые библиотеки, с которыми станет легче собирать UI для аутентификации и отправлять запросы в Firestore в реальном времени.

  • Новая функциональность Firestore Object/Document Mapping для Flutter доступна в альфа-канале.

Стабильный канал

Почти все плагины FlutterFire уже перешли из беты в стабильный канал.

Плагины, которые перешли в стабильный канал для Android, iOS и веб, включают:

Кроме того, в этом релизе добавился контроль установленных приложений (Installations). Плагин App Check и поддержка платформы macOS всё ещё находятся в бета-канале, так как библиотеки Firebase пока тоже в бета-канале. 

Realtime Database, Analytics и Remote Config теперь — полноценные плагины, готовые к использованию в продакшене.

Инициализация Firebase через Dart

С переходом пакетов в стабильный канал мы добавили возможность инициализировать Firebase на любой из поддерживаемых платформ средствами Dart:

import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart'; // generated via `flutterfire` CLI

Future<void> main() async {
  // initialize firebase across all supported platforms
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

  runApp(MyApp());
}

Программный код инициализирует приложение Firebase способом, соответствующим определённой поддерживаемой платформе, согласно информации в файле firebase_options.dart:

static const FirebaseOptions web = FirebaseOptions(
  apiKey: 'AIzaSyCZFKryCEiKhD0JMPeq_weJguspf09h7Cg',
  appId: '1:111079797892:web:b9195888086158195ffed1',
  messagingSenderId: '111079797892',
  projectId: 'flutterfire-fun',
  authDomain: 'flutterfire-fun.firebaseapp.com',
  storageBucket: 'flutterfire-fun.appspot.com',
  measurementId: 'G-K029Y6KJDX',
);

Комментарий Евгения Сатурова

Изменение, которое прошло малозаметным, но… как же это прекрасно. Лишний раз не лезть в дебри нативных модулей Flutter-проекта всегда приятно. Работать с Firebase стало ещё проще, чем раньше. Экономия времени даже на таких мелочах позволяет сфокусироваться на главном — на качестве и технологичности продуктов.

Но причина моей радости не только в этом улучшении. Ниже вы узнаете про FlutterFire CLI, который возмужал настолько, что позволяет вообще забыть про веб-интерфейс Firebase навсегда. Даже в том случае, если вы ещё не создали Firebase-проект. 

Чтобы подробнее узнать о структуре данных каждого способа инициализации для той или иной платформы, ознакомьтесь с новым инструментом flutterfire CLI.

Этот инструмент отправляется в данные в платформо-специфичных вложенных папках и ищет уникальный bundle ID. Затем использует его, чтобы найти подробную информацию по определённому проекту Firebase для соответствующего платформо-специфичного приложения или даже создать новый проект Firebase и новые платформо-специфичные приложения, если таких нет. 

Какая в этом польза? Больше не надо скачивать и добавлять json-файл в Android-проект, скачивать и добавлять plist файл в iOS и macOS проекты или копипастить код в index.html web-проекта. Не важно, какую из поддерживаемых Firebase платформ вы выбрали, — этот кусочек кода на Dart инициализирует Firebase для приложения.

Однако, возможно, это не единственная инициализация, которую надо будет выполнить, чтобы FlutterFire-приложение заработало. Например, может потребоваться интегрировать символы Crashlytics в Android или iOS сборку. Однако с любым новым Firebase-проектом на это должны уйти считанные минуты.

Используем Firebase с DartPad

Так как FlutterFire инициализируется исключительно средствами Dart, Firebase теперь можно использовать прямо внутри DartPad.

В этом примере показано небольшое приложение-чат, которое использует Flutter, Firebase и DartPad. Их уже можно использовать, не устанавливая. Поддержка Firebase в DartPad уже включает основные API, аутентификацию и Firestore. Со временем в DartPad будут появляться новые сервисы Firebase.

Помимо этого, поддержка FlutterFire в DartPad даёт возможность использовать версию DartPad, встроенную прямо в документы.

В этом примере — документы для Cloud Firestore, в одном из которых написан код для примера приложения. Его можно запускать и редактировать прямо в браузере. Здесь можно создавать тестовый проект или даже копипастить код. Всё необходимое будет под рукой.

Firebase UI

У большинства приложений, которые интегрируются с Firebase, есть процесс аутентификации. В том числе — возможность залогиниться с помощью электронной почты и пароля или через аккаунт в другом сервисе, например, Google. 

Firebase Authentication позволяет создавать новый аккаунт в два счёта, подтверждать адрес электронной почты, менять пароль, а в некоторых случаях — выполнить двухэтапную верификацию через SMS, залогиниться через номер телефона или даже объединить несколько пользовательских аккаунтов в один.

Пакет flutterfire_ui умеет воплощать основные сценарии аутентификации с минимальным количеством кода. Представим, что в проекте Firebase доступна аутентификация через email и Google-аккаунт:

С этим пакетом можно создать процесс аутентификации следующим образом:

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutterfire_ui/auth.dart';
import 'firebase_options.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => MaterialApp(
        home: AuthenticationGate(),
      );
}

class AuthenticationGate extends StatelessWidget {
  const AuthenticationGate({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => StreamBuilder<User?>(
        stream: FirebaseAuth.instance.authStateChanges(),
        builder: (context, snapshot) {
          // User is not signed in - show a sign-in screen
          if (!snapshot.hasData) {
            return SignInScreen(
              providerConfigs: [
                EmailProviderConfiguration(),
                GoogleProviderConfiguration(
                  clientId: 'xxxx-xxxx.apps.googleusercontent.com',
                ),
              ],
            );
          }

          return HomePage(); // show your app’s home page after login
        },
      );
}

Этот код инициализирует Firebase. Если он заметит, что пользователь ещё не залогинился, покажет экран регистрации. В виджете SigninScreen есть возможность аутентификации через email и Google-аккаунт. Кроме того, код анализирует аутентификационное состояние пользователя с помощью пакета firebase_auth: как только пользователь зарегистрируется, вы сможете показать ему все остальные экраны приложения. С помощью этого кода вы получаете рабочий процесс авторизации для всех платформ, поддерживаемых Firebase: Android, iOS, веб и macOS.

Выполнив ещё несколько действий, вы с лёгкостью можете вставить изображение и какой-нибудь кастомный текст (подробнее в документации) и таким образом выстроить полноценный процесс входа в приложение:

Мобильная версия
Мобильная версия
Экраны flutterfire_ui адаптивны. Отображение на десктопном устройстве
Экраны flutterfire_ui адаптивны. Отображение на десктопном устройстве

Если у пользователей уже есть email и пароль, они могут их ввести и войти в приложение. Если они используют авторизацию через Google, приложение покажет им классический процесс авторизации через Google-аккаунт, независимо от того, мобильная это версия, веб- или десктопная. Если у них ещё нет аккаунта, они могут нажать на кнопку на экране входа в приложение и перейти на экран регистрации. 

После входа в приложение или регистрации, приложение может показать пользователю экраны валидации электронной почты, смены забытого пароля, выхода из аккаунта и привязки аккаунта социальной сети для последующей аутентификации. Вход через email работает на всех платформах. Также есть возможность авторизации через аккаунты Google, Facebook и Twitter. Она частично поддерживается для Apple, но не работает на Android. Аутентификация с flutterfire_ui поддерживает несколько сценариев и схем навигации. Помимо этого, у flutterfire_ui есть возможность кастомизации и локализации. Подробная информацию и примеры — в документации на firebase.flutter.dev.

Аутентификация — не единственная связанная с Firebase UI фича, которую поддерживает flutterfire_ui. Чтобы в реальном времени показать пользователю список данных из запроса Firebase с возможностью бесконечной прокрутки, мы включили в этот релиз FirestoreListView, который можно добавить в приложение с активным запросом следующим образом:

class UserListView extends StatelessWidget {
  UserListView({Key? key}) : super(key: key);

  // live Firestore query
  final usersCollection = FirebaseFirestore.instance.collection('users');

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(title: const Text('Contacts')),
        body: FirestoreListView<Map>(
          query: usersCollection,
          pageSize: 15,
          primary: true,
          padding: const EdgeInsets.all(8),
          itemBuilder: (context, snapshot) {
            final user = snapshot.data();

            return Column(
              children: [
                Row(
                  children: [
                    CircleAvatar(
                      child: Text((user['firstName'] ?? 'Unknown')[0]),
                    ),
                    const SizedBox(width: 8),
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisAlignment: MainAxisAlignment.center,
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Text(
                          '${user['firstName'] ?? 'unknown'} '
                          '${user['lastName'] ?? 'unknown'}',
                          style: Theme.of(context).textTheme.subtitle1,
                        ),
                        Text(
                          user['number'] ?? 'unknown',
                          style: Theme.of(context).textTheme.caption,
                        ),
                      ],
                    ),
                  ],
                ),
                const Divider(),
              ],
            );
          },
        ),
      );
}

Так список выглядит в приложении:

А если вы хотите, чтобы пользователи могли создавать, читать, обновлять и удалять элементы таблицы, в FirestoreDataTable уже появляются такие возможности:

class FirestoreTableStory extends StatelessWidget {
  FirestoreTableStory({Key? key}) : super(key: key);

  // live Firestore query
  final usersCollection = FirebaseFirestore.instance.collection('users');

  @override
  Widget build(BuildContext context) {
    return FirestoreDataTable(
      query: usersCollection,
      columnLabels: const {
        'firstName': Text('First name'),
        'lastName': Text('Last name'),
        'prefix': Text('Prefix'),
        'userName': Text('User name'),
        'email': Text('Email'),
        'number': Text('Phone number'),
        'streetName': Text('Street name'),
        'city': Text('City'),
        'zipCode': Text('Zip code'),
        'country': Text('Country'),
      },
    );
  }
}

Вот как это работает:

Подробнее об аутентификации, list view и таблицах данных — в документации по flutterfire_ui. Это предварительный релиз, и мы добавим в него новые фичи. Если у вас есть вопрос или вы знаете, какую фичу нужно добавить, перейдите в репозиторий на GitHub и сообщить о баге или задать вопросы в разделе обсуждений.

Комментарий Евгения Сатурова

Если вы рассматриваете Flutter в первую очередь как инструмент для прототипирования или быстрой сборки MVP, значимость flutterfire_ui трудно переоценить.

В наших проектах пакету вряд ли найдётся широкое применение. Чем компоненты более верхнеуровневые, тем больше они несут на борту различных ограничений. А мы любим Flutter совсем не за это, а как раз наоборот — за свободу и гибкость.

Firestore Object/Document Mapping

И последняя, но от того не менее важная фича для интеграции Firebase с Flutter — это релиз Firestore Object/Document Mapper в альфа-канале. Цель Firestore ODM – повысить продуктивность Flutter-разработчиков, упростив работу с Firestore с помощью уже знакомых структурно упорядоченных объектов и методов из безопасной системы типов. С помощью кодогенерации Firestore ODM дорабатывает синтаксис, необходимый для взаимодействия с документами и коллекциями. Это позволяет разработчику моделировать данные типобезопасным способом:

@JsonSerializable()
class Person {
  Person({required this.name, required this.age});

  final String name;
  final int age;
}

@Collection<Person>(‘/persons’)
final personsRef = PersonCollectionReference();

С помощью данных типов можно делать запросы типобезопасным способом:

personsRef.whereName(isEqualTo: 'Bob');
personsRef.whereAge(isGreaterThan: 42);

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

Будем рады вашим отзывам. Чтобы оставить отзыв или задать вопрос, присоединяйтесь к треду о Firestore ODM в обсуждении FlutterFire.

Десктопная версия

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

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

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

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

Кроме того, продолжаем расширять поддержку visualDensity во Flutter и применяем выравнивание к диалогам, чтобы сделать UI удобнее для десктопных устройств.

Команда Flutter — не единственная, кто работает над десктопной версией Flutter. Команда разработчиков для десктопов в Canonical в сотрудничестве с Invertase занимается реализацией наиболее популярных плагинов Firebase для Flutter на Linux и Windows. И это только один из примеров.

Подробнее о предварительном релизе — в блоге Invertase.

DartPad

Рассказ о релизе Flutter будет неполным, если не упомянуть, как мы усовершенствовали инструментарий. В этом посте сконцентрируемся на улучшениях в DartPad. Крупнейшее из них — расширение поддержки пакетов: теперь можно импортировать 23 пакета. Помимо ряда сервисов Firebase, в список вошли популярные пакеты: bloc, characters, collection, google_fonts и flutter_riverpod. Команда DartPad продолжает добавлять новые пакеты. Чтобы посмотреть, какие пакеты поддерживает DartPad, щёлкните по иконке информации в нижнем правом углу.

Чтобы посмотреть, какие пакеты мы планируем добавить в DartPad в будущем, переходите на статью в Dart wiki.

Мы добавили в DartPad ещё одну удобную фичу. Раньше он всегда запускал последнюю стабильную версию. Теперь можно выбрать свежие релизы в бета-канале или предыдущий стабильный релиз (который называется «old channel») в новом пункте меню «Channel» в строке состояния.

Эта фича пригодится, если вы, например, пишете пост в блоге о свежем релизе, и последняя стабильная версия для него недостаточно свежая.

Комментарий Евгения Сатурова

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

Прощаемся с каналом dev

Во Flutter «каналы» отличаются тем, насколько быстро в фреймворк и движок вносятся изменения: канал «stable» претерпевает минимум изменений, а канал «master» меняется максимально часто. 

Недавно мы прекратили обновлять канал dev. Оказалось, что им пользуется 3% Flutter-разработчиков. Наши ресурсы ограничены, поэтому мы официально начинаем его сворачивать. Если вы всё время проводите в стабильном канале (как и более 90% Flutter-разработчиков), разницы вы не заметите.

Выбрать, какой канал вы хотите использовать, можно с помощью команды flutter channel. Вот что думает о каждом канале команда Flutter:

  • Канал stable представляет самые качественные из имеющихся сборок. Новые сборки выходят (примерно) раз в квартал, а в промежутках мы выпускаем hotfix критических ошибок. Этот канал – «медленный»: предлагаемые решения безопасны, проработаны и прослужат долго.

  • Канал beta – динамичная альтернатива стабильному каналу для тех, кто чувствует себя комфортно в часто меняющейся обстановке. На данный момент релизы выходят раз в месяц, а перед релизом канал стабилизируется. Этот канал – «быстрый». Если мы поймём, что канал dev удовлетворял потребностям, которым не отвечает beta-канал, мы возможно изменим свой подход к beta-каналу. Например, будем выпускать обновления в beta-канале чаще или сократим число тестов и hot fix.

  • Канал master – канал активной разработки. На нём нет поддержки, но мы прогоняем его через обширный набор модульных тестов. Этот канал подходит для контрибьюторов и продвинутых пользователей, которых не пугают нестабильные сборки. На этом канале мы постоянно что-то делаем и ломаем. И чиним тоже постоянно.

В течение ближайших месяцев мы свернём канал dev. Рекомендуем присмотреться к каналам beta и master и выбрать подходящий.

Комментарий Евгения Сатурова

Еще полтора-два года назад некоторые наши проекты действительно «сидели» на dev-канале. В те времена Flutter был сыроват, а квартальный релизный цикл стабильного канала никак не позволял быстро получить исправления некоторых неприятных багов фреймворка (за хотфиксы респект, но спасали они не всегда).

Мы уже давно официально не рекомендуем использовать dev, просто потому что это больше не имеет особого смысла. Теперь dev-каналу официально пришёл конец. 

Критические изменения

Мы стремимся свести число критических изменений к минимум в каждом релизе. В релизе Flutter 2.8 критических изменений нет, кроме устаревших API, которые получили статус «deprecated» и были удалены в соответствии с нашей политикой критических изменений.

  • 90292 Удалены autovalidate

  • 90293 Удалён FloatingHeaderSnapConfiguration.vsync

  • 90294 Удалён AndroidViewController.id

  • 90295 Удалён BottomNavigationBarItem.title

  • 90296 Удалены классы для форматирования вводимого текста

Если вы ещё пользуетесь этими API и хотите узнать, как обновить свой код, прочитайте гайд по миграции на flutter.dev. Мы очень благодарны сообществу за тесты, с помощью которых мы находим критические изменения.

Подведём итоги

Провожая 2021 год, наша команда Flutter хотела бы искренне поблагодарить Flutter-сообщество за труд и поддержку. И хотя мы безусловно развиваем Flutter для того, чтобы с каждым годом им пользовалось всё больше разработчиков по всему миру, не будет преувеличением, если я скажу, что мы бы никогда не справились с задачей без вашей помощи. Сообщество Flutter — уникальные люди, и мы благодарны вам за ваши старания. Чудесных вам праздников! Увидимся в новом году!

Комментарии (5)


  1. DeepFakescovery
    18.12.2021 15:01
    -9

    а напомните пожалуйста, ченжлоги различного софта мы теперь на хабре должны читать?


    1. insecto
      20.12.2021 20:21

      Нет конечно, все добровольно, никакой принудиловки.


      1. DeepFakescovery
        20.12.2021 21:20

        а отказаться как? не нашел как поставить в игнор, чтобы это говно в ленте не возникало


  1. Tuwogaka
    18.12.2021 21:53
    +3

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

    По поводу десктопа у Гугла сначала был энтузиазм, бету и альфу ввели в релиз, причём спрятав сведения о том в документацию, чтобы на поверхности в глаза не бросалось. Потом был откат, когда якобы по результатам опроса пользователей решили сосредоточится на другом. Теперь маятник качнулся обратно к энтузиазму. Чего так?

    Потому, что Flutter это от Фуксии, а что там с Фуксией неизвестно, но проявления налицо? Потому, что чего там в приложениях люди делают Гугол не видит, а с Flutter и Firebase имеет шанс одним глазком подсмотреть, особенно кстати когда смартфоны достигли пределов развития (© Microsoft) и ожидается что народ шарахнется с них обратно на десктоп и планшет? Потому, что вера в обновление Playgrounds испытывала приливы с отливами, но как-то реагировать по любому было нужно?

    Я ждал комментария про десктоп...


  1. anonymous
    00.00.0000 00:00