Наш ведущий разработчик Евгений Самойлов (@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-разработчиков, поэтому такой необходимости пока нет.

Фреймворк — понятный и модульный. При создании приложений можно работать с отдельными модулями, которые поддерживаются на разных уровнях, вплоть до совсем хардверных (например, 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, отталкивались от трёх моментов:

  1. Наличие экспертизы в команде

  2. Необходимость легко интегрироваться с уже написанным кодом на С++

  3. Ещё была идея доставлять 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 — всё будет понятно и так.

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


  1. AndronNSK
    07.06.2023 05:24
    +11

    С Qt вы забудете дорогу в StackOverflow — всё будет понятно и так

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

    К сожалению, реально кроссплатформенной альтернативы кути нет.


    1. Ritan
      07.06.2023 05:24
      +1

      Причем не просто забили. Активно вносят новые. И тоже успешно не чинят


    1. Goron_Dekar
      07.06.2023 05:24
      +1

      Тут у ребят комерческая лицензия. И у них этот баг починен.

      Должны же троли (как они там теперь называются, не помню) как-то заставлять вас покупать лицензию.


      1. Rusrst
        07.06.2023 05:24

        Нет у них уже коммерческой лицензии наверняка, уже и приложения в сторе нет. Хотя мне оно нравится к примеру больше чем ya maps. Да и СДК поприятней чем у ya на первый взгляд.


      1. lexa
        07.06.2023 05:24

        Или не починен.

        Мне периодически прилетают уведомления "ваш баг 4-летней давности мы не починили, а закрыли по таймауту"


      1. abagnale
        07.06.2023 05:24

        Наличие коммерческой лицензии не гарантирует, что баг починят (хотя и немного повышает его приоритет). Если взять до сих пор незакрытые багрепорты с тегом "reported_by_support_standard" (то есть, зарепорченные клиентами с коммерческой лицензией) с тяжестью P2 и выше (хотя можно и все посчитать, будет ещё внушительнее) и созданные более трёх месяцев назад (чтобы уж хоть сколько-то времени дать им на починку), то найдётся довольно немало, самый старый из которых висит с 2008 года, и это результаты только по основному проекту, а ещё есть всякие аддоны и инструменты.


      1. pererat_rs
        07.06.2023 05:24

        QT же из России ушел?


        1. apro
          07.06.2023 05:24

          Qt же из России ушел?

          Публично они только закрли загрузку бинарных сборок.
          Что в общем-то бессмысленно, после их нововведений с LTS,
          так как всем кто не платит "Qt Group" и так приходиться собирать их исходников или пользоваться сборками не от "Qt Group".

          А вот как они поступили со своими платными клиентами из России неясно,
          в публичном объявлении они просто предлагали связаться с ними.


    1. HemulGM
      07.06.2023 05:24

      На плюсах, возможно, но есть, например, Delphi с полностью кроссплатформой (FMX)


  1. Breathe_the_pressure
    07.06.2023 05:24

    Мы компилируем и линкуем это в «исошку» (.iso) и получаем нативную библиотеку, которая включается в сборку Android Gradle-ом. 

    А в Андроид дальше как подключается? Через JNI, или ещё какие-то адекватные способы появились? (давно уже не делал таких проектов, но помню муторно было с JNI)


    1. Helius
      07.06.2023 05:24
      +4

      JNI, муторно, но большая часть работы с платформой сделана в Qt, руками приходится дописывать только свои интеграции. У 2Gis на гитхабе есть репозиторий с полезными штуками https://github.com/2gis/qtandroidextensions


  1. magrif
    07.06.2023 05:24

    А какими способами отлаживаете приложение, собранное под Android, если надо искать сложные баги, не воспроизводимые на десктопе? Можно в креаторе одновременно ставить бряки в kotlin части и C++?


    1. Helius
      07.06.2023 05:24
      +2

      Баги только на android бывают довольно редко, чаще всего удается воспроизвест на desktop. Если же нет, то можно настроить отладчик android-studio, он умеет в native


  1. QtRoS
    07.06.2023 05:24
    +2

    Класс! Почему-то интуитивно думал, что вы ушли с Qt где-то в момент перехода к пока-еще-не-совсем super-app. Здорово, что фреймворк все еще удовлетворяет нуждам.

    P.S. Некоторое время назад к моей статье был (почему-то сейчас нет, видимо автора забрал НЛО) комментарий вроде "вау, Qt такое может в мобайле?". Передаю вам эстафетную палочку :)


  1. nerudo
    07.06.2023 05:24

    Что мешает выпустить версию для десктопа, если оно на QT?


    1. DrMefistO
      07.06.2023 05:24

      А смысл? GPS на десктопе вроде не частое явление.


      1. AlexanderS
        07.06.2023 05:24

        Тут уже больше смысл в оффлайновых картах.


        1. DrMefistO
          07.06.2023 05:24

          Оффлайновые карты для десктопа? Это что-то странное.

          Иду я по лесу с ноутом, заблудился. Открыл оффлайн карты - нашёл выход из леса?)


          1. AlexanderS
            07.06.2023 05:24

            Иногда нужно что-то и просто так посмотреть. Или глянуть как там по маршруту будет. Раньше это удивление не вызывало.


            1. DrMefistO
              07.06.2023 05:24

              Раньше и интернет был диалап. А именно тогда я оффлайн картами с компа и пользовался.


              1. AlexanderS
                07.06.2023 05:24

                Раньше и программы с картами были. А сейчас карты-то пакетом можно заранее скачать, а вот с "настольным" софтом совсем не густо. Есть, конечно, OsmAnd, но на компе что-то смотреть всё же удобнее, чем на смарте.


                1. apro
                  07.06.2023 05:24

                  Есть, конечно, OsmAnd, но на компе что-то смотреть всё же удобнее, чем на смарте.

                  Если Linux, то можно собрать https://github.com/organicmaps/organicmaps/ у него наряду с GUI для iOS/Android есть GUI на Qt для PC.
                  А может он уже есть собранный для вашего дистрибутива.


  1. scorpion1574
    07.06.2023 05:24
    +2

    Я пишу на qml-е уже год и могу сказать, что разработка на нем крайне не удобная. У qml не встроен hotreloader, что замедляет разработку. Есть библиотека-дополнение qt felgo, в котором встроен hotreloader, но он поддерживает только 5 версию qt. Javascript на версии 5.15.2 по нынешней разработке устарел. У него нету ни fetch, ни Map, ни Set. Большую часть логики и выдачу данных приходится писать на c++-qt. А это долго, ты пока напишешь модель, унаследованную от QAbstractItemModel, проинцилизируешь ее в qml, пройдет полдня. Qml не умеет распознавать std контейнеры, поэтому должна идти дополнительная связка с qt core и std. А сама IDE qt creator, такое ощущение, что вообще не развивается. Она не умеет перетаскивать файлы, если нужно эти файлы переместить. Qt уже на 6-ой версии, которая активно использует cmake, но при этом IDE при добавлении новых cpp файлов, не умеет добавлять их в конфиг cmake. IDE просто копирует их местоположение в буфер, чтобы ты самостоятельно их вставил в конфиг.

    И это только вершина айсберга. За все время программирования на данной технологии, мои идеи для проектов спотыкались об реализацию QML.


    1. cdriper
      07.06.2023 05:24

      Javascript на версии 5.15.2 по нынешней разработке устарел

      я не думаю, что Qml в принципе предназначен для написания жирной бизнес-логики

      хотите много писать на js, ну так сразу берите Electron или что-то в таком духе

      ты пока напишешь модель, унаследованную от QAbstractItemModel

      пишется один раз, потом переиспользуется


    1. slonopotamus
      07.06.2023 05:24
      +3

      ты пока напишешь модель, унаследованную от QAbstractItemModel, проинцилизируешь ее в qml, пройдет полдня

      Просто пишите быстрее!


  1. Okker
    07.06.2023 05:24

    Сегодня мы бы выбирали между Qt, Kotlin и Jetpack Compose (а Flutter, думаю, оказался бы в пролёте — даже год назад нам приходилось самим писать библиотеки или искать их на «Гитхабе»)

    Вы собираетесь полностью переезжать на другой фреймворк? Есть ли какие-то причины возможного переезда? Интересно узнать, какие инструменты используются для работы с графическими объектами на айфонах)


    1. Rusrst
      07.06.2023 05:24

      Compose то не подойдёт - карта же наверняка в surface (или что там ещё есть низкоуровневое) рендерится. Compose не поддерживает surface без androidview, если только не сделать обёртку над картами, а интерфейс уже в compose делать.