- 1. Створення проекту на Java
- 2. Створення проекту на Qt QML
- 1. Крок 1 - Виберемо створення порожнього Qt Quick програми
- 2. Крок 2 - Виберемо місце розташування проекту
- 3. Крок 3 - вибір системи складання
- 4. Крок 4 - Вибір версії бібліотеки Qt
- 5. Крок 5 - Вибір комплекту збирання
- 6. Крок 6 - Вибір системи контролю версій
- 7. Програмний код
- 8. Система складання та AndroidManifest.xml
- 3. Висновок
Заради цікавості вирішив порівняти два варіанти написання додатків під Андроїд. Колись давно починав займатися програмуванням під Андроїд Java, але згодом перейшов на розробку Desktop додатків на Qt QML. Але тепер знову вирішив освіжити у пам'яті деякі аспекти, щоб переконатися, що Qt QML мені подобається більше.
Відразу наведу результат двох Hello world`ів. Вони звичайно не будуть на 100 відсотків ідентичні, але мають бути схожими. Як базовий приклад візьму порожню Activity, яка створюється в Android Studio.
Перший зразок – це Hello World на Java
Другий зразок – це Hello World на Qt QML
Загалом додатки схожі, зовнішній вигляд відрізняється трохи в рендерингу тексту, та у додаткових ефектах. У решті програми однакові.
Для початку почнемо з Java програми.
Створення проекту на Java
Крок 1 - Виберемо пункт створення нового проекту
Крок 2 - Дамо ім'я проекту
Крок 3 - виберемо мінімальний SDK проекту
Крок 4 - Виберемо тип проекту - Empty Activity
Крок 5 - Налаштування Activity
На цьому проект буде створено та налаштовано. Можете одразу його зібрати та запустити на вашому смартфоні. У мене розмір apk , зібраного в режимі debug склав приклад 170 кБ.
Програмний код
А тепер подивимося на те, як виглядає програмний код програми.
Програми під Андроїд Java складаються з двох програмних шарів:
- XML-верстка програми, яка представляє собою інтерфейс програми, його зовнішній вигляд. І фактично не має жодної програмної логіки.
- Java-логіка програми, яка відповідає саме за всю логіку бізнесу і т.д. і т.п.
XML-версія
Якщо чесно... верстка всіх властивостей зовнішнього вигляду програми в XML виглядає досить громіздкою, при тому, що немає можливості використовувати будь-яку програмну логіку для зміни властивостей чи тексту елементів. Ця складність особливо очевидна, коли доводиться описувати досить складні інтерфейси.
Але подивимося xml-код.
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.evileg.javahelloworld.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>
Тут можна побачити, що описується саме поле з текстом Hello World, але не описується зовнішній вигляд ToolBar
а, який є активітом. Наявність ToolBarа визначається через контекст активіті, що використовується в даному випадку.
А ось у QML на жаль доведеться писати такий самий ToolBar самостійно.
Код Java
Сам Java код буде невеликим, оскільки знадобиться лише перевизначити метод створення Activity , щоб встановити в неї XML верстку. А те, яку активувати стартувати, визначаємо в AndroidManifest.xml .
package com.evileg.javahelloworld; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
Створення проекту на Qt QML
Крок 1 - Виберемо створення порожнього Qt Quick програми
Крок 2 - Виберемо місце розташування проекту
Крок 3 - вибір системи складання
Можете вибрати за смаком:
- qmake
- cmake
- qbs
Не знаєте, що вибрати, вибирайте qmake
Крок 4 - Вибір версії бібліотеки Qt
Вибирайте останню стабільну версію (вона має бути у вас встановлена)
Крок 5 - Вибір комплекту збирання
Ось чим мені подобається Qt, так це тим, що програми на QML можна збирати як під Desktop, так і під Android пристрої. Тобто, якщо ви не тестуєте платформозалежний функціонал, то можна сміливо збирати під робочий стіл і вести все тестування на вашому ПК і лише періодично перевіряти, як програма працює на Android пристрої.
Крок 6 - Вибір системи контролю версій
Для Hello World`а нам не знадобиться система контролю версій.
Програмний код
Проекти на Qt QML зазвичай складаються з двох програмних шарів, як і у випадку з Java.
- C++ шар - на ньому може бути написана основна бізнес-логіка, складні розрахунки, робота з мережею і т.д.
- QML шар - на ньому реалізується зовнішній вигляд програми, а також деяка логіка, втім ніщо не заважає реалізувати всю бізнес-логіку на QML, якщо додаток та можливості дозволятиму. Також QML досить добре підтримує JavaScript, на якому і реалізовуватиметься ця логіка.
Тобто в деяких випадках ніщо не заважає взагалі використовувати C++.
main.cpp
Цей файл створюється за замовчуванням. У цьому випадку ми запускаємо двигун QML і малюємо вміст main.qml файлу.
#include <QGuiApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
QMLHelloWorld.pro
Проектний файл Qt, в ньому прописуються всі ресурси, а також вихідні файли проекту з налаштуванням збирання. Він також потрібний тут крім файлу AndroidManifest.xml
QT += quick CONFIG += c++11 # The following define makes your compiler emit warnings if you use # any feature of Qt which as been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if you use deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += main.cpp RESOURCES += qml.qrc \ images.qrc # Additional import path used to resolve QML modules in Qt Creator's code model QML_IMPORT_PATH = # Additional import path used to resolve QML modules just for Qt Quick Designer QML_DESIGNER_IMPORT_PATH = # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target DISTFILES += \ android/AndroidManifest.xml \ android/gradle/wrapper/gradle-wrapper.jar \ android/gradlew \ android/res/values/libs.xml \ android/build.gradle \ android/gradle/wrapper/gradle-wrapper.properties \ android/gradlew.bat ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
main.qml
А ось і найцікавіше. У цьому файлі знадобиться створити не лише текст HelloWorld, а й створити ToolBar з іконкою та ім'ям програми. Я взяв іконку з проекту на Java і додав її в ресурси проекту на Qt QML.
import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.3 import QtQuick.Controls.Material 2.1 ApplicationWindow { visible: true width: 360 height: 520 title: qsTr("Hello World") header: ToolBar { height: 48 Rectangle { anchors.fill: parent color: "#080808" Image { id: ico height: 36 width: 36 anchors { left: parent.left leftMargin: 10 top: parent.top topMargin: 6 } source: "qrc:/images/ic_launcher.png" } Text { anchors { verticalCenter: parent.verticalCenter left: ico.right leftMargin: 4 } text: qsTr("QmlHelloWorld") font.pixelSize: 18 color: "white" } } } Label { anchors.centerIn: parent text: qsTr("Hello World!") font.pixelSize: 14 } }
Код вийшло однозначно більше, ніж у файлі верстки XML для програми на Java. Але давайте розберемося. Так вийшло тому, що в Qt QML спочатку немає ніяких активів. Взагалі робота всього докладання відбувається в одній єдиній активіті, і немає жодної необхідності перемикатися між цими активіти. Зробити поведінку програми, подібну до зміни Активіті, можна за допомогою Loader, StackView, SwipeView та багатьох інших компонентів. А тут використовується компонент вікна, який має місце для розміщення ToolBar
а, потрібно лише написати верстку даного ToolBarа
Так от, якби подібний ToolBar був спочатку, то написання тексту Hello World виявилося б менш громіздким, ніж у випадку з Java. Тобто було б таким
import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Controls 2.3 import QtQuick.Controls.Material 2.1 ApplicationWindow { visible: true width: 360 height: 520 Label { anchors.centerIn: parent text: qsTr("Hello World!") font.pixelSize: 14 } }
Проти цього в XML
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.evileg.javahelloworld.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>
І, якщо чесно, варіант з QML виглядає більш читаним.
Система складання та AndroidManifest.xml
Система складання в обох випадках використовувалася Gradle.
Що стосується AndroidManifest.xml, то у випадку з Java жодних додаткових маніпуляцій не було. Тоді як у випадку з Qt потрібно додати іконки запуску. Про роботу з AndroidManifest.xml у Qt можна прочитати докладніше у цій статті .
Висновок
В обох випадках можна отримати дві однакові програми, а ось в нюансах розробки можна буде визначитися, що і кому буде зручніше.
Обидва варіанти пропонують працювати у двох шарах
- Java + XML
- QML + C++
Але у випадку з QML/C++ всю логіку можна написати тільки на QML, а в першому випадку в XML можна написати лише верстку.
Початковий Hello World буде написаний досить швидко на Java. Достатньо буде лише створити проект, а щоб отримати подібний результат на Qt QML, то доведеться ще трохи коду написати. Однак, у ряді випадків доведеться писати значно менше коду на QML, ніж Java/XML.
З мінусів Qt я б відразу відзначив те, що є платформозалежні моменти, які все одно доведеться вирішувати через Java, наприклад події від ОС Android. Однак... також деякі проблемні частини проекту вирішують через C++, у проекті Java, тому тут швидше буде паритет.
З плюсів Qt наголосив би на тому, що в останніх версіях вони підтримують Material Design , що також полегшить розробку програми, коли дизайнера немає як такого в проекті.
Розмір зібраного APK, тут звичайно виграє Java. У debug режимі вихідний APK з Java вийшов всього 170 кБ, тоді як APK від Qt вийшов 10 мБ, в реліз складання розмір APK Qt буде приблизно 5-6 мБ, але я б не назвав це настільки критичним, оскільки багато великих програм у Google Play важать 40-60 мБ і в результаті розміри зрівняються.
Інші аспекти розглянемо у наступних статтях.
Разрешите узнать, как вы получили qt+qml приложение размером в 10мб(даже релизных). Дело в том, что пустое приложение, хоть и со стек вью, обходится мне на все 40мб пространства. Или же вы воспользовались ministro? Спасибо за ответ!
Добрый день. На тот момент ничего не использовал дополнительно и никаких специальных настроек не делал. Просто собрал и получилось 10 мб.