Чтобы забраться на высокую гору, сначала нужно подняться на небольшую высоту и побыть там некоторое время, чтобы организм привык к разреженному воздуху и отсутствию визуальных точек опоры. То же самое я рекомендую проделать тем, кто решится взобраться на гору мобильных разработок, прожив всю жизнь в равнине десктопных приложений и баз данных. А в качестве обзорной площадки выбрать App Inventor – бесплатный онлайн сервис, созданный Массачусетским Технологическим Институтом для обучения студентов разработке мобильных приложений.

В этой статье я расскажу о своем опыте создания рабочего прототипа приложения, хранящего и обрабатывающего пользовательские данные. Так как много лет я занимаюсь разработкой приложений для Windows, то частенько буду анализировать разницу в подходах создания мобильных приложений и программ для “окошек”.

Что взять с собой?

В первую очередь – оптимизм. Веру в себя и в тех парней, кто раньше ходил по этой тропинке и дошел до цели.

Если есть алгоритмическая база и понимание принципов построения программ – тоже берите, пригодится. Если нет – ничего страшного: App Inventor создан в первую очередь как средство обучения, поэтому всё самое необходимое можно на месте.

Что оставить дома?

Надежду найти могущественные компоненты, которые реализуют необходимый вам функционал. Возможно, что они существуют, и возможно, что стоимость их будет для вас приемлимой, но если тратить на это время при первой прогулке, то можно не заметить главного: логика работы с данными у мобильных приложений сильно отличается от логики десктопных программ.

Желание сделать красивый интерфейс. App Inventor – это история не про красоту, а про функциональность. И это правильное начало для знакомства с любой средой разработки. Минимум визуальных опций и настроек позволит вам сконцентрироваться на результате: на функционировании приложения и решения задач пользователя.

Вперёд!

Переходим на сайт MIT App Inventor, регистрируемся и получаем бесплатный доступ к конструктору приложений.

Создание мобильного приложения состоит из двух взаимосвязанных процессов: проектирование экранов в режиме дизайнера и сборка обработчиков событий из графических элементов-пазлов. Также из пазлов собираются переменные, которые могут иметь довольно сложную структуру. Интерфейс имеет русскую локализацию, что удобно для самостоятельного изучения, но не совсем удобно при просмотре обучающих видео или чтении учебных материалов – большинство из них на английском языке.

Экран

Экран (Screen) – это не форма. Это процесс. Он может иметь или не иметь пользовательский интерфейс. Программа состоит из одного или нескольких таких процессов, один из которых будет главным и запускаться при старте программы.

Экран – самодостаточная единица, в том смысле, что в App Inventor нет глобальных переменных: все данные для работы экрана находятся внутри экрана, за исключением ресурсов – файлов с изображениями или звуками. То же самое относится к блокам выполнения действий (обработчикам событий) – их область видимости – экран приложения.

Название главного экрана – Screen1, оно не редактируется. Вы можете добавить до 9 дополнительных экранов и назвать их по своему усмотрению. Это не так уж много, поэтому старайтесь размещать компоненты на одном экране, для переключения внешнего вида менять видимость контейнеров.

Дизайнер

В режиме дизайнера слева расположена палитра компонентов, из которой можно брать и перетягивать их в центральную часть – на экран мобильного устройства с выбранными в настройках разрешением экрана. Справа расположено дерево компонентов экрана, список загруженных в проект медиа-данных и панель со свойствами выбранного компонента.

Выбор размеров экрана небогат, как и число поддерживаемых версий Android. Зато не запутаетесь в настройках SDK и прочих библиотек, от которых крышу сносит в Delphi или Android Studio.

Блоки

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

Поначалу это кажется забавным и удобным: цвета соответствуют категории блоков, наглядность реализации алгоритмов радует глаз. Но если кода много, то радость сменяется судорожными прокручиваниями рабочей поверхности с целью найти искомую картинку…

Зато есть встроенный генератор картинок, чтобы вставлять код в виде иллюстраций в документы и сайты:

Данные и представления

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

Продолжительность жизни процесса – величина неизвестная. Только вы открыли нужное приложение (процесс), как зазвонил телефон или мессенджер, или вам срочно понадобился навигатор или ещё сотня других приложений… Операционная система при нехватке ресурсов (а их, как выяснилось, всегда не хватает) вынуждена выбрасывать скрытые от глаза пользователя процессы из памяти, а потом снова загружать их, как только вы захотите к ним вернуться. Поэтому все данные, которые пользователь вводит или которые вычисляются в процессе работы, необходимо при первой же возможности сохранять в постоянную память телефона или куда-нибудь ещё (например в облачные хранилища). А как только приложение возвращают к жизни загружать эти данные. И в этом деле вы – главный и отвечаете за результат, так как ни компоненты, ни приложение не умеет автоматизировать эти процессы.

Концепцию архитектуры можно выразить несколькими тезисами:

  • Данные хранить в переменных.
  • Визуальные компоненты использовать для отображения данных из переменных или ввода данных в переменные.
  • Содержимое переменных необходимо сохранять в постоянной памяти и восстанавливать их значение из памяти при активации процесса (экрана).

Вроде бы звучит неплохо, но на практике это означает, что большая часть создаваемого вами кода будет предназначена для перекачивания и переформатирования данных, а не для вычислений или других алгоритмов. Для разработчиков My Visual Database или Delphi это будет выглядеть как некий откат в прошлое, в джунгли плотного взаимодействия с файлами и другими сервисами ОС.

NUMERO 2

Программа выполняет вычисления и поиск по базе данных. Состоит из главного экрана, который отвечает за ввод (выбор) исходных данных, и дополнительных экранов, в каждом из которых реализована своя обработка и свои данные для хранения.

Всё время хочется использовать слово “таблицы данных”, но никаких таблиц не будет, от слова “совсем”.

Главный экран

Раскладка элементов напоминает слоёный пирог. Так и есть: это контейнеры, содержимое которых выравнивается по горизонтали и растянуто по вертикали, а сами контейнеры выравниваются по вертикали и растягиваются по горизонтали. Ну и тематическая картинка заполняет оставшуюся часть экрана. Кстати, она же выполняет роль иконки приложения. А вот какая начинка у этого пирога:

  • Название программы: метка “NUMERO”.
  • Главное меню: кнопки “Пифагор”, “Арканы”, “Циклы”, “Сервис”.
  • Дата рождения: метка, поле ввода, картинка, выбор даты и кнопка “Найти”.
  • Фамилия: метка и поле ввода.
  • Имя: метка и поле ввода.
  • Отчество: метка и поле ввода.
  • Меню данных: кнопки “Сбросить” и “Записать”, картинка индикатора записи (скрыта).
  • Изображение.

Чуть ниже располагаются “невидимые компоненты” для сохранения данных в памяти (TinyDB1) и отображения диалогов (Notifier1) – так в MIT перевели на русский язык понятие “не визуальные компоненты”. Поэтому в обычной работе я предпочитаю английский интерфейс, но для иллюстрации этой статьи переключил его на русский.

Не совсем типичная форма для приложения, эдакий гибрид формы редактирования и главной формы. Остальные формы (экраны) будут больше похожи на те, которые обычно используются при разработке приложений в My Visual Databfse и других средах разработки для Windows-приложений.

Блоки

Прежде, чем разбирать, как работает NUMERO, несколько слов о графическом языке программирования, который используется в App Inventor.

Блоки – это элементы кода. По сути – лексические единицы языка программирования. Каждый блок имеет определенный цвет, который соответствует его типу:

  • Управление: команды, меняющие ход выполнения программы; циклы, условные операторы, вызовы других экранов и т.д.
  • Логика: логические операторы и константы: OR, AND, NOT, True, False; проверка равенства двух объектов.
  • Математика: математические константы, операторы и функции: сложение, вычитание, синус, косинус и т.д.; всё, что использует в качестве аргумента или возвращает числовое значение.
  • Текст: константы, операторы и функции для работы с текстом; соединение, поиск вхождения, замена, определение длины и т.д.
  • Массивы: функции и процедуры для работы со списками; создание, поиск, перебор, сортировка и т.д.
  • Dictionaries: работа со словарями; создание, добавление, редактирование, поиск по ключу и т.д.
  • Цвета: константы и операторы для работы с цветом.
  • Переменные: инициализация глобальных/локальных переменных, запись/чтение значения переменной.
  • Процедуры: операторы для описания и вызова процедур и функций.

Таким образом, имеет следующие базовые типы данных:

  • Логический
  • Числовой
  • Текстовый

Преобразование типа производится автоматически, в зависимости от типа используемых операторов и функций. То есть тип переменной определяется типом данных, которые в него поместили.

Остальные типы автоматически не преобразуются. При этом некоторые компоненты могут производить подобные преобразования, но, как правило, в одну сторону (например, списки или словари – в текст). И это может оказаться ловушкой, так как в других объектных моделях (например, в Delphi) свойство объекта обычно является симметричным относительно чтения/записи. Я сам попался в эту ловушку, когда предположил, что раз содержимое списка можно сохранить, как текст, то его же можно и считать из текста. Но это не так.

Переменные

Всё, что вы намереваетесь использовать, сначала нужно декларировать. И это мне нравится 🙂

ПеременнаяТипНазначение
BDateТекстДата рождения в формате DD.MM.YYYY
Name1ТекстФамилия
Name2ТекстИмя
Name3ТекстОтчество
NameListСписокСписок людей с указанием дня рождения
NameIndexЧислоИндекс выбранного в списке человека

Объявление переменной выгладит так: нужно взять блок инициализации переменной, разместить в рабочей области и ввести название переменной. Затем взять блок-константу нужного типа и присоединить справа.

Хранилище

Как я уже говорил ранее, при запуске экрана нужно загружать данные, которые вносил пользователь. Чтобы упростить эту операцию, можно использовать БД, которая хранит в себе пары <ключ> + <значение>, причем и ключ и значение – это текст. Для этого используется не визуальный компонент TinyDB. Он находится в палитре компонентов, в разделе “Хранилище”.

Так как инициализация переменных будет происходить в двух случаях (при активации экрана и после выбора данных на другом экране), я оформил инициализацию в виде процедуры UpdateNames().

“Текст” процедуры говорит сам за себя. Отмечу лишь, что в последнем блоке устанавливается видимость картинки DataSaved, которая является индикатором того, что данные о человеке были успешно сохранены в список персон NameList.

Инициализация экрана выглядит так:

Свойство Namespace (область имен) позволяет разделить общую кучу, куда валятся данные в TinyDB на несколько кучек поменьше, и дать ей своё имя. Даже если у вас данных немного, рекомендую для каждого приложения создавать свою уникальную область имен. Это связано с тем, что если вы будете использовать утилиту отладки, запускаемую на телефоне, то она будет использовать одно же физическое хранилище для всех отлаживаемых программ, что может привести к коллизиям данных из разных приложений, если у них совпадут ключи.

Продолжение следует.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *