Flutter в действии

1.

Flutter в действии
Глаза боятся, а попробовать хочется
Сатуров Евгений
Android Teamlead, Surf
saturov
1

2.

Flutter в действии
Глаза боятся, а попробовать хочется
Сатуров Евгений
Android Flutter Teamlead, Surf
saturov
2

3.

-
Android/Flutter Teamlead
FlutterDevPodcast
PC Mobius
GDG Voronezh Lead
3

4.

Этот доклад для вас, если вы:
• Уже прочитали все статьи на Хабре про то, «как я запустил Hello World, и что из
этого вышло»;
• В курсе, что Flutter позволяет быстро создавать красивые приложения, и хотите
узнать, правда ли это;
• Чувствуете дискомфорт при фразе «Всё – это виджеты»;
• Хотите посмотреть на чудаков, которые уже запилили Flutter в продакшн;
• Пришли в этот зал, потому что в соседнем непонятный айосный доклад.
4

5.

Часть 0.
То, что вы уже знаете про Flutter.
5

6.

Очень скучный слайд
• Flutter – мультиплатформенный open-source фреймворк;
• Приложения пишутся на Dart;
• Под капотом свой графический движок (Skia) и рантайм (Dart VM);
• Официально поддерживаются две платформы: iOS и Android;
• Неофициально ещё ряд других (веб, десктоп, носимые и встраиваемые ОС).
6

7.

*все картинки кликабельны
7

8.

Архитектура фреймворка
UI (контролы, анимации, стилизация, user input);
Виджеты и стейт-менеджмент.
Skia (графический движок);
Dart (Runtime, GC);
Text (LibTxt).
Отрисовка на канве;
Нативные плагины.
8

9.

Архитектура фреймворка
UI (контролы, анимации, стилизация, user input);
Виджеты и стейт-менеджмент.
Skia (графический движок);
Dart (Runtime, GC);
Text (LibTxt).
Отрисовка на канве;
Нативные плагины.
https://github.com/flutter/flutter
9

10.

Всё своё ношу с собой
UI (контролы, анимации, стилизация, user input);
Виджеты и стейт-менеджмент.
Skia (графический движок);
Dart (Runtime, GC);
Text (LibTxt).
Отрисовка на канве;
Нативные плагины.
10

11.

Типы сборок и компиляция
Debug
Release
JIT
AOT
• Low FPS;
• High FPS;
• «Тяжёлое» приложение
(> 40 Мб);
• «Лёгкое» приложение
(>7 Мб).
• Работает Hot Reload.
11

12.

Типы сборок и компиляция
• Android - Gradle;
• iOS – Xcode Build;
• Flutter Assemble – coming soon.
12

13.

Часть 1.
Наш опыт.
13

14.

За последние полгода мы:
• Собрали команду;
• Написали 3 небольших приложения и стартанули большой финтех;
• Выработали ряд лучших практик и своё видение архитектуры;
• Заложили основу линейки переиспользуемых модулей, которые планируем
шарить в open-source.
14

15.

Начинать работать
с новой технологией надо так,
чтобы о твоём позоре
никто не узнал.
15

16.

«Вселенная Парк»
16

17.

«Вселенная Парк»
17

18.

Карта экранов
18

19.

Проект в цифрах
• 2 разработчика;
• 560 чел./час;
• 62% таски, 22% отладка, 15% на поболтать;
• 6 полноценных эпиков-фич;
• 76% попадание в собственные оценки.
19

20.

Распределение времени
20

21.

Первый «подопытный» был выбран правильно
Не было написано ни строчки платформенного кода, всё покрыто плагинами:
• Yandex Mapkit
• Camera
• Permission Handler
• Shared Preferences
• QR Flutter
• и многими другими.
21

22.

Flutter-приложение дешевле*
• *чем два нативных приложения;
• Команда разработки на 40% меньше;
• Более линейные процессы;
• Больше времени остаётся на разработку фичей.
22

23.

NDA
Финтех
23

24.

Часть 2.
Рекламная.
24

25.

25

26.

• По-сравнению с двумя нативными
приложениями - вероятно;
• Когда ты понимаешь, с какой стороны
подступиться к задаче;
• Когда ты способен заранее оценить
трудозатраты (не всегда);
• Когда приложение не заточено на
глубокую работу с платформенными API.
26

27.

27

28.

• Нативный Look & Feel сам себя не сделает – это возможно, но вручную;
• Apple-юзеры всё ещё находят отличия в UI (не понимаю, как они это делают);
• Для унифицированного UI/UX – идеально.
28

29.

Максимальная мимикрия
29

30.

30

31.

• Нет бутылочных горлышек на
рендеринге (прощай, JavaScript Bridge);
• Простота реализации асинхронных задач
– миф (Future исполняется в UI-потоке);
• Из коробки «летать» не будет.
Берём профайлер, лучшие практики и
вперёд!
31

32.

32

33.

Часть 3.
Жизненная.
33

34.

FLUTTER-ЛИД ПОСЛЕ СОБЕСЕДОВАНИЯ
34

35.

Ищу Flutter-разработчика
Требуемый опыт: 1-3 года.
35

36.

Немного сухой статистики
Октябрь
Сентябрь
Август
0%
10%
20%
30%
40%
Вакансии
50%
60%
70%
80%
90%
100%
Резюме
36

37.

Бэкграунд нашей Flutter-команды
6
1
1
37

38.

Бэкграунд нашей Flutter-команды
6
38

39.

Без «яблока» не обойтись
• Собрать билд локально;
• Настроить Firebase;
• Пофиксить специфичный баг вёрстки;
• Разобраться, почему не работает… (подставь свой вариант);
• Написать полноценный платформенный плагин;
39

40.

Назад в будущее (пишем на Dart)
• Не Kotlin;;;;;;;;;;;;;;;
• Однопоточный (но есть Isolate);
• Нет модификаторов доступа: _приватность;
• Нет перегрузки функций;
• Mixins – интерфейсы с реализацией;
• Enum без состояния;
• Нет data-классов, нет null-safety (Null – это тип), нет sealed-классов и многого
другого.
40

41.

Dart.equals(Java) == true?
static String normalize(String inputString, {bool withPrefix = false}) {
StringBuffer buff = StringBuffer();
for (var i = 0; i < inputString.length; i++) {
String o = inputString[i];
if (int.tryParse(o) != null) {
buff.write(o);
}
}
String res = EMPTY_STRING;
if (withPrefix) {
res += PHONE_PREFIX;
}
res += buff.toString();
return res;
}
41

42.

Async/await
Future<Shop> _findNearestShop() async {
final userLocation = await _locInteractor.getLocationSafe().single;
final shops = await getShops(
lat: userLocation.latitude,
lon: userLocation.longitude,
).single;
shops.sort((shop1, shop2) => _compareShops(sh1, sh2, userLocation));
return shops.first;
}
42

43.

«Выучу только Flutter и Dart!»*
* не сказал ни один успешный Flutter-разработчик
43

44.

• Flutter + Dart;
• Android + Kotlin;
• iOS + Swift;
• App Store Connect + TestFlight;
• Google Play Console + Firebase App Distribution.
44

45.

Периодически каждый из нас
45

46.

https://pub.dev/flutter
46

47.

https://pub.dev/flutter
47

48.

Не очень хорошие популярные плагины
• https://pub.dev/packages/permission_handler - в вашем iOS-приложении будут
указаны вообще все существующие пермишны, даже если они не используются;
• https://pub.dev/packages/flutter_local_notifications - конфликтует с другими пушплагинами, например firebase_messaging.
48

49.

Самое время собирать «звёздочки»
Dagger
inject.dart
Retrofit
Dio
RxJava
RxDart
49

50.

Пример HTTP-запроса через Dio
import 'package:dio/dio.dart';
void getHttp() async {
try {
Response response = await Dio().get("http://www.google.com");
print(response);
} catch (e) {
print(e);
}
}
50

51.

Firebase что-то знает
• firebase_core
• firebase_dynamic_links
• firebase_messaging
• firebase_remote_config
• firebase_analytics
• firebase_ml_vision
• firebase_auth
• firebase_performance
• firebase_storage
• firebase_in_app_messaging
• firebase_database
• И все остальные модули.
• firebase_crashlytics
• firebase_admob
51

52.

Проверенные нами плагины
• https://pub.dev/packages/flutter_svg – поддержка векторной графики (позволяет
использовать *.svg);
• https://pub.dev/packages/camera – удобное API для работы с камерой (фото +
видео);
• https://pub.dev/packages/flutter_masked_text – маскирование полей ввода;
• https://pub.dev/packages/device_info – получение информации о девайсе.
52

53.

Если у вас есть время
53

54.

Хорошая новость:
• На Flutter можно написать вообще всё что угодно;
54

55.

Плохая новость:
• На Flutter можно написать вообще всё что угодно;
• Для этого нужно знать очень много разных вещей;
55

56.

Плохая новость номер два:
• На Flutter можно написать вообще всё что угодно;
• Для этого нужно знать очень много разных вещей;
• Не всегда после этого становится понятно, зачем вообще было всё это писать
на Flutter.
56

57.

Можно ли сделать на Flutter {$featureName} ?
Да, можно.
• Dart (UI, бизнес-логика);
• Platform Channels + Native Plugins (Kotlin, Swift и т.д.);
• Platform Views;
• C/C++ direct interop using FFI.
57

58.

История про бесшовную авторизацию.
(из новейшего опыта)
58

59.

У нас были…
• Два нативных «легаси» приложения;
• Сложнейшая процедура инициализации сессии с необходимостью подписи
сертификата ЭЦП в веб-версии сервиса;
• Несколько десятков тысяч пользователей, которые уничтожили бы компанию в
случае массового разлогина при обновлении приложения.
59

60.

Можно ли сделать на Flutter {$featureName} ?
Да, можно.
• Dart (UI, бизнес-логика);
• Platform Channels + Native Plugins (Kotlin, Swift и т.д.);
• Platform Views;
• C/C++ direct interop using FFI.
60

61.

Схема авторизации
Auth
Credentials
Authentication
61

62.

Auth
Credentials
Auth
Credentials
Authentication
Authentication
62

63.

Platform
Credentials Provider
Provide
Auth
Credentials
Flutter
Credentials Provider
Authentication
63

64.

Инициализация MethodChannel
const _platform = MethodChannel(_authProviderChannelName);
64

65.

Платформенный поставщик Credentials
class PlatformAuthDataProvider {
Future<Uint8List> getCert(String userId, String pinHash) {
return _platform.invokeMethod(
getCertificateMethodName,
[userId, pin],
);
}
65

66.

Платформенный поставщик Credentials
class PlatformAuthDataProvider {
Future<Uint8List> getCert(String userId, String pinHash) {
return _platform.invokeMethod(
getCertificateMethodName,
[userId, pin],
);
}
66

67.

Платформенный поставщик Credentials
class PlatformAuthDataProvider {
Future<Uint8List> getCert(String userId, String pinHash) {
return _platform.invokeMethod(
"fghvfkajsr/m1kjnbaf",
[userId, pin],
);
}
67

68.

Это вам не a.a.b.c()
68

69.

Так, так, так… секьюрити
• Реверс-инжиниринг практически бесполезен;
• Обфускация в Dart существует, но…
Note: that obfuscation support is not very well tested
and might not work at the moment.
• Самое уязвимое место – Method Channels со стороны платформенного кода (да
поможет нам ручная обфускация).
69

70.

MainActivity.kt
MethodChannel(
flutterView,
authProviderChannelName
).setMethodCallHandler { call, result ->
launch {
val output: Any = when (call.method) {
albhsfsadg -> {
val arguments: List<String> =
call.arguments as List<String>
authDataProvider.getCert(args[0], args[1])
}
70

71.

Platform
Credentials Provider
Provide
Auth
Credentials
Authentication
Migrate
Auth
Credentials
Flutter
Credentials Provider
71

72.

Hot Reload спасает жизнь при разработке
72

73.

Но на CI/CD запасайтесь поп-корном
73

74.

Джентельменский деплой-набор
• Fastlane;
• Firebase App Distribution.
74

75.

Часть 4.
Вдохновляющая.
75

76.

Переход на Flutter – это не смена работы
• Подходы;
• Синтаксис языка;
• Архитектура.
Всё это знакомо и привычно любому мобильному разработчику.
76

77.

Больше времени с друзьями и близкими
• Применение изменений: ≈ 2-3 сек.
• Синхронизация проекта: ≈ 5-10 сек.
77

78.

Настало время для крутого вызова
• Нет проверенных лучших практик;
• Нет надежды на то, что кто-то поможет (даже SOF);
• С каждой проблемой ты можешь столкнуться впервые;
• Нужно обдумывать каждый шаг и брать на себя ответственность;
• Никому нельзя доверять.
78

79.

79

80.

Ссылки на меня
https://twitter.com/saturovv
https://www.facebook.com/saturov
https://habr.com/ru/users/saturovv/
Telegram: @saturov
80

81.

Ссылки на полезные ресурсы
https://flutter.dev/
https://flutter.dev/docs/codelabs
https://www.youtube.com/channel/UCwXdFgeE9KYzlDdR7TG9cMw
https://habr.com/ru/company/google/blog/426701/
81
English     Русский Правила