Модуль фоновой обработки операций сообщается с несколькими компонентами приложения, не все из которых требуют обратной связи для отчёта о выполнении операций. Таким образом, можно выделить две раздельные цепочки данных, первая из которых используется для обновления состояния кэша, а вторая - для чтения данных из БД.
Первая цепочка представлена следующим набором последовательных операций:
. Пользовательский ввод.
. Реакция на ввод в активити.
. Отправка команды сервису фоновой обработки.
. Вызов удалённого веб API.
. Получение данных в формате JSON.
. Преобразование данных к виду, используемому на клиенте.
. Передача данных для обновления в БД.
С другой стороны, вторая цепочка описывается следующим образом:
. Старт активити.
. Создание загрузчика и подписка его на обновления БД.
. Ожидание обновления и передача данных в активити по готовности.
. Переход к пункту 3 для отслеживания актуальности данных.
Стоит отметить, что цепочки независимы друг от друга и инициируются различными модулями. Кроме того, одновременно запускается сразу несколько цепочек второго типа, при этом они могут начать своё выполнение не дожидаясь окончания первой цепочки. Данная схема является работоспособной за счёт того, что операции обновления БД инициируются модулем фоновой обработки операций, а операции чтения данных из БД выполняются модулями загрузки данных после того, как модуль работы с БД выдаст событие об успешном обновлении данных.
3. Функциональное проектирование
В данном разделе подробно рассматривается
функционирование программных модулей. Перечислены все присутствующие классы и
большинство их компонентов. Состав и отношения классов также показаны на
диаграмме классов (чертёж ГУИР.400201.128 РР.2).
.1 Описание взаимодействия с сервером
Одной из главных функций мобильного клиента является обмен данными с сервером. Для этих целей был разработан интерфейс, описывающий набор веб-методов для коммуникации между компонентами. Иными словами, интерфейс программирования приложений (application programming interface, далее API). API базируется на трёх основных принципах:
. Формат передаваемых данных - JSON.
. Информация о пользователе передается с каждым запросом при помощи базовой аутентификации HTTP (Basic Authentication).
. Для отправки данных используются HTTP POST запросы.
На данный момент сервер предоставляет пять веб-методов доступных клиенту, описание которых представлено ниже. Методы перечислены в порядке их вызова приложением. Как только пользователь нажимает кнопку «Войти» на экране авторизации, вызывается метод login для проверки прав доступа. Если доступ получен, приложение по очереди вызывает методы stores и categories для обновления локального кэша, в то время как пользователь может делать снимок. После того как пользователь сделает фото, он попадает на страницу метаданных, заполнив которые, отправляет фото на сервер, другими словами производится вызов методов upload_photo и save_photo.
. Авторизация пользователя (../api/login)
Входные данные:
{
}
Ответ сервера:
{
"role": "user"
}
Описание:
Данный метод используется для первоначальной авторизации пользователя и получение его роли, которая может быть использован в дальнейшем. На текущий момент существует три роли: «user», «merchandizer» и «admin». Любая из данных ролей позволяет пользоваться приложением, хотя в дальнейшем это поведение может быть изменено, в частности, некоторые функции могут стать недоступными для некоторых ролей.
. Получение списка магазинов (../api/stores)
Входные данные:
{
"version": 10
}
Ответ сервера:
[
{
"id": 102,
"version": 11,
"active": true,
"name": "Coolman",
"street": "Кульман",
"city": "Минск"
},
...
]
Описание:
Метод возвращает список магазинов, обновившихся после запрошенной версии (поле «version» из входных данных). При каждом изменении данных о магазине на сервере должен увеличиваться номер версии. Номер версии является глобальным для клиента и сервера счетчиком. Клиент при запросе отправляет максимальную версию из имеющихся у него. Важной особенностью системы является то, что данные о магазинах никогда не удаляются, однако им можно присваивать неактивный статус (поле «active» из ответа сервера). Неактивные магазины не отображаются при выборе точки продажи на клиенте.
. Получение списка категорий (..api/categories)
Входные данные:
{
"version": 10
}
Ответ сервера:
[
{
"id": 3,
"version": 6,
"active": true,
"name": "Computers"
},
...
]
Описание:
Метод возвращает список категорий, обновившихся после запрошенной версии. (поле «version» из входных данных). Метод аналогичен предыдущему, но вместо списка магазинов получает список категорий товаров. Номер версии также является глобальным для клиента и сервера, а категории, аналогично магазинам, не удаляются, а переводятся в неактивный режим.
. Загрузка фотографии (../api/upload_photo)
Входные данные:
Фото в бинарном виде.
Ответ сервера:
{
"file": "3F2504E0-4F89-11D3-9A0C-0305E82C3301"
}
Описание:
Метод используется для загрузки фотографий на сервер. После загрузки сервер генерирует уникальный идентификатор для файла (GUID) и сохраняет его под этим именем в хранилище, после чего возвращает идентификатор в качестве ответа на запрос. Клиент после успешной загрузки файла использует идентификатор для передачи дополнительной информации, связанной с файлом при вызове следующего метода.
. Сохранение фотографии (../api/save_photo)
Входные данные:
{
"store": 102,
"category": 12,
"comment": "User defined comment",
"problem": false,
"was_taken": "unknown"
"file": "3F2504E0-4F89-11D3-9A0C-0305E82C3301",
"coordinates": {
"latitude": 54.3,
"longitude": 23.4,
"accuracy": 10
}
}
Ответ сервера:
{
"success": true
}
Описание:
Метод используется для сохранения загруженной ранее фотографии с идентификатором, переданным в качестве параметра «file» запроса. В данном случае в теле POST-запроса передаются метаданные снимка, которые включают в себя следующие элементы:
- идентификатор магазина («store»);
- идентификатор категории («category»);
- произвольный комментарий («comment»);
- специальное поле «was_taken», позволяющее определить снимок как сделанный до, либо после работы; возможные значения: «unknown» (по умолчанию), «before» или «after»;
- идентификатор файла («file»);
- координаты точки, в которой была сделана фотография (структура «coordinates»), включающие в себя широту («latitude»), долготу («longitude») и точность определения («accuracy»).
В случае неправильного логина или пароля, любой
из выше перечисленных методов возвращает ошибку в виде HTTP
ответа с кодом 401 - «Unauthorized». Ответ сервера сделан непустым на случай,
если понадобится добавление расширенных сообщений об ошибках.
3.2 Описание классов системных компонентов
Классы системных компонентов, применительно к данному проекту, представляют собой класс Worker Service, наследованный от класса Intent Service, а также четыре класса, унаследованные от класса Acivity: Login Activity, Settings Acivity, Camera Activity и Data Activity. Особенностью данных классов является то, что они описывают тот или иной крупный компонент приложения, важный, в первую очередь, для ОС.
Для четырёх активити-классов можно выделить несколько общих методов, определённых в базовом классе и часто переопределяемых в классах наследниках. Эти методы вызываются в различные моменты жизненного цикла активити и служат для корректной обработки смены стадий жизненного цикла.
- void onCreate(Bundle savedInstanceState) - метод, вызываемый при создании активити. В нём осуществляется создание и размещение (inflatting) визуальных компонентов (обычно из специального файла с разметкой), а также начальная инициализация компонентов. Данный метод можно рассматривать как аналог конструктора, с той лишь разницей, что на момент вызова активити будет уже не только создана, но и отображаться на экране телефона. Объект типа Bundle является контейнером, содержащим пары ключ-значение и служит для восстановления параметров при пересоздании активити после поворота экрана или иной смены конфигурации.
- boolean on Create Options Menu (Menu menu) - метод, вызываемый при создании контекстного меню активити, пункты которого добавлялись к объекту menu. На данный момент шаблон проектирования с использованием контекстного меню устарел и в этом методе производится инициализация так называемой «строки действий» (Action Bar), являющей актуальным на данный момент дизайнерским шаблоном для предоставления контекстно зависимых опций. В отличие от контекстного меню, строка действий, обычно, инициализируется не в коде, а в файле разметки. Возвращаемое методом значение служит индикатором для создания меню: если метод вернёт false, то контекстное меню создано не будет, даже если оно будет инициализировано значениями. Такое поведение справедливо также и для строки действий.
- boolean on Options Item Selected (MenuItem item) - метод вызываемый при выборе пункта меню или действия со строки действий (в действительности, это одно и то же: разница лишь в терминологии и способе отображения). Объект типа Menu Item ассоциирован с визуальным элементом, обрабатывающим нажатие, а возвращаемое значение является индикатором окончания обработки нажатия: если метод возвращает false, для определённого пункта меню, значит нажатие на него будет обработано в другом месте.
- void on Resume() - метод, вызываемый непосредственно перед отображением активити на экране. В данном методе обычно производится возобновление всех временно прерванных процессов.
- void on Pause() - метод, вызываемый при переходе активити в неактивный режим. Иными словами, каждый раз, когда активити пропадает с экрана. В данном методе обычно приостанавливаются все связанные с пользовательским интерфейсом процессы, а также производится сохранение состояния важных переменных.
- void on Activity Result (int request Code, int result Code, Intent data) - данный метод представляет собой обработчик результатов, полученных от действий инициируемых с помощью интентов, например, таких, как вызов активити, содержащей детальное представление или получение информации от датчиков телефона. В данном случае request Code - уникальный идентификатор интента, result Code - код результата, обычно показывающий успех или ошибку, data - непосредственно сам интент с результатами выполнения запроса.
- void on Click (View view) - данный метод не является частью класса Activity, однако очень часто используется в его наследниках. Данный метод является единственным компонентом интерфейса View. On Click Listener, который должны реализовать объекты-слушатели событий-кликов по визуальным элементам управления. Существует два основных подхода к обработке кликов, каждый из которых имеет свои преимущества и недостатки: либо для каждого элемента управления создаётся свой класс-слушатель (обычно анонимный), либо активити реализует интерфейс View. On Click Listener и становится слушателем для всех свои элементов управления. В данном проекте используется второй способ.
Помимо этих методов, можно отметить наличие в классах-активити целочисленных констант вида «ACTION_CODE_XXX» и строковых констант вида «YYY_DIALOG_TAG».
Константы первого типа представляют собой уникальные ключи, используемые при создании интентов. Они необходимы для идентификации результатов, полученных в качестве ответа на определённые интенты. Идентификатор, заданный при создании интента будет в последствии передан в метод on Activity Result в качестве параметра requestCode. Значения целочисленных констант формируются из трёх цифр наподобие кодов HTTP ответов. Первая цифра показывает компонент (класс), которому принадлежит константа, вторая - область применения константы (идентификатор интента, идентификатор загрузчика и т.д.), третья - порядковый номер константы в рамках заданного компонента и области применения.
Константы второго типа представляют собой идентификаторы-теги диалоговых окон. Согласно новым шаблонам проектирования, диалоговые окна представляют собой фрагменты, унаследованные от базового класса Dialog Fragment. Это сделано для того, чтобы не сохранять состояние диалоговых окон каждый раз, когда пользователь поворачивает экран или сворачивает приложение нажатием кнопки домой. Диалоговые окна, основанные на фрагментах, имеют свой жизненный цикл, не зависящий от жизненного цикла активити, поэтому они могут быть созданы одним экземпляром класса, а использоваться другим. Для того, чтобы не было путаницы, каждый диалоговый фрагмент отмечается тегом, по которому его всегда можно найти.
Класс Login Activity
Данный класс ассоциирован с активити авторизации - первым, что видит пользователь приложения. Основными его функциями являются авторизация пользователя и обработка самого первого запуска приложения.
Константы:
- ACTION_CODE_LOGIN - идентификатор интента, ассоциированного с действием авторизации.
- PROGRESS_DIALOG_TAG - тег диалогового фрагмента, используемого для отображения прогресса выполнения задачи.
- REPORT_DIALOG_TAG - тег диалогового фрагмента, используемого для отображения информации об ошибках.
- REDIRECT_DIALOG_TAG - тег диалогового фрагмента, используемого для переадресации на страницу на строек при первом запуске приложения.
- SAVE_CREDENTIALS_PROPERTY - константа-ключ для доступа к опции запоминания логина и пароля.
Поля:
- Save Credetials - поле типа boolean, содержащее актуальное значение опции запоминания логина и пароля.
- Login Edit Text - поле типа Edit Text, содержащее ссылку на текстовое поле для ввода имени пользователя (логина).
- Password Edit Text - поле типа Edit Text, содержащее ссылку на текстовое поле для ввода пароля.
- Save Credentials Check Box - поле типа Check Box, содержащее ссылку на флажок опции запоминания логина и пароля.
- Signin Button - поле типа Button, содержащее ссылку на кнопку «Войти».
- Progress Dialog - поле типа Progress Dialog Fragment, содержащее ссылку на диалоговый фрагмент, используемый для отображения прогресса выполнения задачи.
- Preferences - поле типа Shared Preferences, содержащее ссылку на модуль настроек.
Методы:
- void try Begin Authorize User() - метод, осуществляющий валидацию пользовательского ввода перед операцией авторизации, а также отображающий результаты валидации.
- void begin Authorize User (String login, String password) - метод, запускающий процесс асинхронной авторизации. В качестве входных параметров выступают введённые пользователем логин и пароль.
- void end Authorize User(String role) - метод, вызываемый при окончании авторизации. Входным параметром является роль пользователя.
- void navigate To Camera Activity () - метод, осуществляющий переход к активити управления камерой.
- void before Text Changed (Char Sequence char Sequence, int i, int i2, int i3) - метод интерфейса Text Watcher. Не используется.
- void on Text Chan ged (Char Sequence char Sequence, int i, int i2, int i3) - метод интерфейса Text Watcher. Не используется.
- void after Text Changed (Editable editable) - метод интерфейса Text Watcher. Вызывается послед ввода каждого символа. Разблокирует кнопку signin Button при наличии логина и пароля.
- boolean on Editor Action (Text View text View, int i, Key Event key Event) - метод интерфейса Text Watcher. Данный метод обрабатывает нажатия специальных кнопок клавиатуры, например, кнопки «Далее».
- void report Error (int message Id) - метод, осуществляющий отображения диалога с информационным сообщением. Сообщение хранится в ресурсах приложения, в то время как метод принимает идентификатор ресурса - message Id.
- void show Redirect Dialog () - метод, осуществляющий отображения диалога для перенаправления на страницу настроек.
- void restore Properties () - метод, осуществляющий восстановление ранее введённых данных.
- void save Preferences () - метод, осуществляющий сохранение текущего состояния активити.