Evgenii Legotckoi
Evgenii Legotckoi19 февраля 2018 г. 2:13

Android. Java vs Qt QML - Урок 001. Hello World

Любопытства ради решил сравнить два варианта написания приложений под Андроид. Когда-то давно начинал заниматься программированием под Андроид на 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 состоят из двух программных слоёв:

  1. XML-вёрстка приложения, которая представляет из себя интерфейс приложения, его внешний вид. И фактически не имеющей никакой программной логики.
  2. 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 мБ и в итоге размеры сравняются.

Остальные аспекты рассмотрим в следующих статьях.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

ГВ
  • 16 ноября 2019 г. 16:16

Разрешите узнать, как вы получили qt+qml приложение размером в 10мб(даже релизных). Дело в том, что пустое приложение, хоть и со стек вью, обходится мне на все 40мб пространства. Или же вы воспользовались ministro? Спасибо за ответ!

Добрый день. На тот момент ничего не использовал дополнительно и никаких специальных настроек не делал. Просто собрал и получилось 10 мб.

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:50баллов,
  • Очки рейтинга-4
m
  • molni99
  • 26 октября 2024 г. 11:37

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80баллов,
  • Очки рейтинга4
m
  • molni99
  • 26 октября 2024 г. 11:29

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:20баллов,
  • Очки рейтинга-10
Последние комментарии
ИМ
Игорь Максимов22 ноября 2024 г. 22:51
Django - Урок 017. Кастомизированная страница авторизации на Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi1 ноября 2024 г. 0:37
Django - Урок 064. Как написать расширение для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 октября 2024 г. 18:19
Читалка fb3-файлов на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов5 октября 2024 г. 17:51
Django - Урок 064. Как написать расширение для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55 июля 2024 г. 21:02
QML - Урок 016. База данных SQLite и работа с ней в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Сейчас обсуждают на форуме
m
moogo22 ноября 2024 г. 18:17
Mosquito Spray System Effective Mosquito Systems for Backyard | Eco-Friendly Misting Control Device & Repellent Spray - Moogo ; Upgrade your backyard with our mosquito-repellent device! Our misters conce…
Evgenii Legotckoi
Evgenii Legotckoi25 июня 2024 г. 1:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey115 ноября 2024 г. 17:04
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProject4 июня 2022 г. 13:49
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…

Следите за нами в социальных сетях