Политика конфиденциальностиКонтактыО сайтеОтзывыGitHubDonate
© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB

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

Qt, JAVA, Android, QML

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

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

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
m
19 декабря 2018 г. 10:37
maintumanov

Qt - Тест 001. Сигналы и слоты

  • Результат:68баллов,
  • Очки рейтинга-1
ИН
18 декабря 2018 г. 17:37
Игорь Носач

C++ - Тест 003. Условия и циклы

  • Результат:64баллов,
  • Очки рейтинга-1
ИН
18 декабря 2018 г. 17:22
Игорь Носач

C++ - Тест 003. Условия и циклы

  • Результат:35баллов,
  • Очки рейтинга-10
Последние комментарии
V
15 декабря 2018 г. 2:06
Vlad15007

Спасибо большое!Очень помогли!
11 декабря 2018 г. 21:01
Евгений Легоцкой

Не знаю, какой-там конкретно эффект и если честно не хочется fl studio ради того, чтобы посмотреть устанавливать, но из того, что увидел в интернете. Предполагаю, что то, что вы хотите с...
V
11 декабря 2018 г. 19:25
Vlad15007

Подскажите пожалуйста ( я новичок совсем)Можно ли организовать спрайт без этого окошка (как в fl studio fruity dance)?
11 декабря 2018 г. 15:06
Евгений Легоцкой

Что интересно, если написать так from <application_name>.<module_name> import <filename> ,то PyCharm сносит крышу, если разрабатываешь в рамках проекта приложение, ко...
11 декабря 2018 г. 14:52
Илья Чичак

Тут мне тоже есть что сказать=) Сами разрабы советуют импортировать следующим образом: from <application_name> import <module_name> Стоит избегать from . import &l...;
Сейчас обсуждают на форуме
М
19 декабря 2018 г. 8:43
Михаиллл

Здравствуйте.Говорят, если подключить ICU, то в SQLite появится регистронезависемый поиск.Я нашел скомпилированный ICU по этой ссылке https://www.npcglib.org/~stathis/blog/precompiled-...
18 декабря 2018 г. 19:58
Евгений Легоцкой

ну если у вас также будет внешний ключ на Serial, то получается следующая ситуация, Movie добавлен в Serial, а Serial имеет список Movie. То есть вам playlist как таковой вовсе не нужен....
R
18 декабря 2018 г. 12:25
RED_Spider

именно так, проблема в кодировке, а именно в отсутствии шрифтов на сервере, для меня вопрос решился в CentOS 7yum install curl cabextract xorg-x11-font-utils fontconfig всем спасибо за ...
U
18 декабря 2018 г. 10:39
Unreal_man

А вот этот коннект здесь и вовсе не нужен connect(ui->ok3, &QPushButton::clicked, this, &Widget::addToText); А как же без него? ============================== ...
m
17 декабря 2018 г. 19:03
melnik10

Спасибо, попробую!
Присоединяйтесь к нам в социальных сетях

Для зарегистрированных пользователей на сайте присутствует минимальное количество рекламы