![](https://habrastorage.org/getpro/habr/upload_files/7c0/b9f/aac/7c0b9faac8f85a900817e20187266a2e.png)
Наш ведущий разработчик Евгений Самойлов (@Helius) недавно сходил в гости к Android Broadcast, где рассказал, почему мы в 2ГИС используем Qt. Для тех, кому удобнее читать, публикую выжимку того разговора.
2ГИС — это сложный продукт с картой, поисковым движком, базой данных, транспортными сценариями и многим другим. У сложного продукта — большое UI-наследие. Чтобы 2ГИС выглядел и работал хорошо на всех Android-устройствах, мы используем фреймворк Qt.
Но ведь Qt — это старый фреймворк?
На Qt пишут уже более 20 лет, но возраст в данном случае не определяет надёжность и качество.
Qt развивается уже очень давно, у него есть порты под Windows, Linux и любые графические бэкенды. Были даже порты под BlackBerry, MeeGo, Sailfish OS и Jolla. С 2018 года он официально поддерживается на Android и iOS, то есть это по-настоящему кроссплатформенная штука. У Qt даже есть поддержка встраиваемых девайсов, на которых нет полноценной графической среды, только очень урезанный Linux — и ничего, после включения «железки» стартует Qt-приложение.
Долгое время в Qt UI писали только на чистом С++, хотя были python-биндинги. Разработчики создавали объекты, верстали прямо в C++ коде или в дизайнере накидывали какие-то формочки. Но это было не так удобно до появления QML, который сделал вёрстку в Qt в разы быстрее и удобней.
Qt любят ребята, которые ценят кроссплатформенность. Например, Tesla использует его для своего UI.
У Qt есть платная лицензия. Компании-пользователи фреймворка заинтересованы в том, чтобы Qt решал их насущные проблемы. И в отличие от opensource-фреймворков, где вектор развития мог определяться другими критериями, Qt много сил тратили на то, чтобы их классы были очень удобными и функциональными, на все случаи жизни. Например, QString — класс для работы со строкой — содержит сотни методов, что угодно с ней можно сделать. Найти подстроку или порезать по символам, регэкспам, форматировать и шаблонизировать как угодно, конвертировать туда-сюда.
Кроме 2ГИС, активно используют Qt в Zoom, Telegram и других известных проектах (например, в операционной системе «Аврора»).
Как Qt выглядит в деле?
В 2ГИС Qt используется для мобильного Android-приложения. Под iOS тоже можно писать на Qt, но у нас сложилась отличная команда нативных iOS-разработчиков, поэтому такой необходимости пока нет.
![](https://habrastorage.org/getpro/habr/upload_files/4d5/6da/8a7/4d56da8a7321a025be489f95b9567b40.png)
Фреймворк — понятный и модульный. При создании приложений можно работать с отдельными модулями, которые поддерживаются на разных уровнях, вплоть до совсем хардверных (например, GPS или сенсоры). Благодаря плагину QPA (Qt Platform Abstraction) можно реализовать поддержку целевой платформы, так сделано под Windows, Linux под разные графические подсистемы, такие как Wayland и OpenGL. В QPA у нас есть набор стандартных интерфейсов под разные платформы: жесты, тачи, кнопки, сенсоры. Это позволяет работать на разных OS.
Когда мы разрабатываем на Qt под Android, то, по сути, пишем десктопное приложение. Его реально можно запустить под десктопом в ограниченном режиме и заниматься разработкой, «не прыгая» по гаджетам. А дальше начинается магия!
Так как Qt это приложение С++, у него есть функция main — точка входа, как у любого приложения, — и куча наших исходников из библиотеки Qt. Мы компилируем и линкуем это в эсошку (.so) и получаем нативную библиотеку, которая включается в сборку Android Gradle-ом.
Вообще говоря, в Qt есть довольно навороченная подсистема, которая помогает собрать все библиотеки и asset-ы, запаковать все это, сгенерить Gradle-проект, манифест и все необходимые вещи для сборки под android. Это нужно, чтобы пользователь мог что-то поднастроить — и получить готовый билд.
Почему в 2ГИС используют Qt, а не React Native?
Мы начали разрабатывать кроссплатформенные приложения более 10 лет назад, когда не было популярных сейчас фреймворков: React Native только разрабатывался, а про Flutter и Kotlin Multiplatform даже и не думали. Если уж и выбирать, то между Xamarin, нативным Android (ну и Qt, конечно). Тем более что на Qt у нас уже было приложение под десктоп, Windows Mobile и под старый Android.
Выбирая Qt, отталкивались от трёх моментов:
Наличие экспертизы в команде
Необходимость легко интегрироваться с уже написанным кодом на С++
Ещё была идея доставлять UI напрямую в приложение без выкладывание новой версии в стор. В итоге эта схема не прижилась.
Это очень важно, ведь у нас огромное приложение, натуральный супер-апп: из 2ГИС можно и заправиться, и заказать пиццу, и построить сложный маршрут с такси и самокатами — сценариев очень много. Поэтому у нас около миллиона строк кода в С++ SDK. Конечно же, мы хотели всё это сохранить и переиспользовать. В 2ГИС мы всегда уделяли дизайну много внимания: продумывали пути пользователя, совершенствовали каждую мелочь. В тот момент средства стандартного Android не давали нам большого преимущества, потому что приходилось бы делать очень много кастомных вещей, а это много часов разработки.
А сегодня Qt по-прежнему актуален?
Сегодня мы бы выбирали между Qt, Kotlin и Jetpack Compose (а Flutter, думаю, оказался бы в пролёте — даже год назад нам приходилось самим писать библиотеки или искать их на «Гитхабе»).
У нас были разработчики, которые не писали на С++ и Qt до того, как попали к нам в команду.
QML содержит в себе JS. Поэтому бывало, что фронтендеры приходили в команду, довольно быстро осваивались с QML и прекрасно верстали UI и писали логику. С другой стороны, может быть, не всегда оправданно писать логику на JS. Всё-таки хочется больше писать «в плюсах», а UI делать максимально тонким.
Некоторое время назад мы начали делать мобильный SDK. Очевидно, что на С++ он мало кого бы заинтересовал: нужен было создавать его под iOS и Android. Но так как у нас огромная база функционала написана на С++, нам потребовалось сделать нормальную интеграцию с Kotlin. SDK-шки есть на нашем сайте: и карты, и навигатор, и поисковик. И если бы прямо сейчас мы выбирали фреймворк, скорее всего, мы бы пошли к парням и поинтересовались, насколько у них всё это хорошо и гладко работает.
А что насчёт оптимизации?
Быстродействие в мире Android — это боль по сравнению с iOS, где люди намного чаще меняют смартфоны, девайсов немного и все они довольно шустрые. Но мы много времени тратим на оптимизацию даже под старые устройства.
Вообще, нельзя сказать, что QML тормозной. Но когда ты делаешь большое приложение, легко допустить ошибку: например, один маленький компонент сделать недостаточно быстрым. И когда ты его используешь в 500 местах на одной странице, она начинает грузиться медленно.
Более сложная задача в оптимизации — это старт приложения, если оно огромное и содержит кучу сервисов. В этой длинной цепочке последовательностей операций на старте нужно загрузить UI, и всегда есть соблазн на первую страницу накидать много готового, чтобы потом не париться и все было сразу доступно. Такое куда сложнее оптимизировать — нужно тюнить прямо на уровне миллисекунд. Это большая работа, которая у нас никогда не останавливается.
Как вообще «въезжать» в Qt в своей команде?
Так как Qt — это, по сути, десктопная штука, вам даже не нужен смартфон. Можно открыть Qt Creator и начать писать код, попутно заглядывая в документацию с кучей примеров в соседнем окошке.
У Qt отличная документация, есть форум и большое комьюнити. Плюс, есть компании, которые пишут статьи и туториалы, создают тулкиты, надстройки над фреймворком.
На мой взгляд, у Qt документация лучше, чем у Android (где местами просто, а местами — тяжело). С Qt вы забудете дорогу в StackOverflow — всё будет понятно и так.