В этой серии руководств мы разработаем нативное приложение для Android, в котором пользовательский интерфейс реализован с использованием фреймворка jQuery Mobile . Для этого мы представим модель для представления экранов пользовательского интерфейса в собственном приложении Android с использованием элементов страницы jQuery Mobile, в частности страниц контейнера и содержимого . Хотя учебный код разработан для управления контактами, основные концепции модели являются общими и могут применяться к приложениям, в которых пользовательский интерфейс подходит для конструирования с помощью HTML и JavaScript.
В рамках модели мы обсуждаем интеграцию JavaScript с внутренним Java-кодом и описываем доступ к методам Java из JavaScript и, наоборот, доступ к JavaScript / HTML из Java.
Краткое изложение основных аспектов создаваемой модели:
- Физическая HTML-страница содержит одну страницу контейнера с одной или несколькими страницами содержимого, где каждая страница содержимого представляет один или несколько экранов пользовательского интерфейса.
- Доступ к Java из JavaScript основан на привязке JavaScript объектов Java, что стало возможным с помощью
addJavascriptInterface()
в классеandroid.webkit.WebView
. - Доступ к JavaScript / HTML из Java осуществляется с помощью
loadUrl()
классаandroid.webkit.WebView
. Этот метод можно использовать для вызова функции JavaScript или для загрузки физической HTML-страницы. - Внутренний код Java работает как служба для кода JavaScript в пользовательском интерфейсе. Код JavaScript вызывает метод Java для запроса определенного действия и определяет функцию JavaScript обратного вызова для получения результатов обратно. В некоторых случаях код JavaScript вызывает метод Java для управления навигацией, который описан ниже.
- Навигация по экрану управляется кодом JavaScript в соответствии со следующими правилами.
- Переход с одной страницы содержимого на другую внутри той же страницы контейнера выполняется кодом JavaScript.
- Переход с одной страницы контейнера на другую выполняется с помощью кода Java с использованием
WebView.loadUrl()
. Отображаемая страница контейнера передается в код Java из JavaScript в качестве параметра. - При передаче объекта из функции JavaScript в метод Java или наоборот, используется представление объекта JSON.
Дополнительные аспекты учебника заключаются в следующем.
- Элементы пользовательского интерфейса для учебного приложения состоят из представлений списка jQuery Mobile, разделителей списка и складных блоков. Мы используем jQuery Mobile версии 1.0 Alpha 3. (Недавно была выпущена версия Alpha 4 с различными исправлениями ошибок. См. Объявление .)
- Согласно API Android, любой не-пользовательский поток, который вызывает
WebView.loadUrl()
должен использовать объектandroid.os.Handler
для доступа к экземпляруWebView
. Мы объясняем, как мы выполнили это требование в нашем учебном приложении. - Мы используем API контактов Android для чтения и управления контактами на устройстве Android. Объясняются различные таблицы базы данных, в которых хранятся основные элементы контакта, такие как телефоны, адреса, электронные письма и т. Д. Мы опишем, как запрашивать эти таблицы с помощью Android API.
- Мы обсуждаем, как разработать проект в Eclipse IDE с помощью плагина Android Development Tools. Описаны файлы конфигурации проекта и даны пошаговые инструкции по импорту исходного кода проекта в среду разработки Eclipse.
Организация обучения
Этот учебник был организован следующим образом. В части 1 «Экран потока» мы представляем экраны в приложении и описываем переходы между этими экранами. Раздел «Структура страницы jQuery Mobile» дает обзор элементов страницы в структуре jQuery Mobile и объясняет, как экраны в этом приложении создаются с использованием этих элементов. В разделе «Интеграция пользовательского интерфейса на основе HTML / JavaScript с Android-бэкэндом» мы рассмотрим основные концепции интеграции пользовательского интерфейса, состоящего из HTML и JavaScript, с внутренними классами Java, которые реализуют бизнес-функциональность. Подразделы здесь: «Доступ к Java из JavaScript», «Доступ к HTML / JavaScript из Java» и «Типы данных параметров в вызовах методов». В «Запуске приложения» мы начинаем проверку кода для конкретных функциональных областей приложения. В каждом разделе мы описываем последовательность событий, которые происходят между пользовательским интерфейсом и серверной частью Java для выполнения определенных действий.
Мы начинаем вторую часть учебника с раздела «Создание учетной записи», в котором описывается, как создать учетную запись для связи с вновь созданными контактами. В разделе «Существующий контакт» мы описываем редактирование и удаление существующего контакта. Часть 3 урока начинается с «Добавление контакта», в котором объясняется, как добавить новый контакт. В ContactUtility
«Чтение контактов через класс ContactUtility
» мы обсуждаем, как использовать API Java Java для доступа и управления контактами на устройстве Android.
В части 4 последней части учебника «Операции записи для контактов» объясняется удаление и сохранение контакта с помощью Android Java API. В этом разделе, а также в разделе «Чтение контактов через класс ContactUtility
» ( часть 3 ) описывается, как использовать JSON-процессор Jackson для преобразования туда-обратно между объектами данных Java и строковыми представлениями этих объектов в формате JSON. В разделе «Конфигурация проекта и вспомогательные файлы» мы обсуждаем файлы конфигурации для проекта. В разделе «Значок запуска приложения» описывается, как мы создали значки запуска для учебного приложения в соответствии с Руководством по разработке значков Android . В «Родной среде разработки приложений Android» мы описываем среду разработки для приложения и объясняем отдельные этапы импорта проекта в Eclipse IDE. Наконец, «Выводы» дают заключительные замечания для этого урока.
Поток экрана
В нашем приложении каждый контакт должен быть связан с учетной записью. Как правило, учетные записи — это идентификаторы пользователя в онлайн-сервисе, таком как «gmail». Для этого демонстрационного приложения мы создадим учетную запись, которая будет владеть всеми контактами, созданными приложением. Для простоты этот аккаунт не будет связан с каким-либо онлайн-сервисом. Контакты, принадлежащие другим учетным записям, будут по-прежнему отображаться через приложение, однако их нельзя редактировать или удалять. (Это ограничение является намеренным, чтобы избежать случайного повреждения контактов в реальном устройстве Android.) При запуске приложения проверяется, была ли создана учетная запись для приложения. При первом запуске учетная запись не существует, поэтому у пользователя отображается экран «Создание учетной записи» (рисунок 1 ниже).
Рисунок 1. Экран создания учетной записи.
После создания учетной записи начальным экраном, отображаемым при запуске приложения, является экран «Список контактов». Экран «Список контактов» отображает список всех контактов в устройстве (рисунок 2 ниже).
Рисунок 2. Экран списка контактов.
Если пользователь нажимает кнопку добавления, отображается экран «Пустой контакт». На этом экране пользователь может ввести новую контактную информацию и сохранить контакт. После сохранения контакта отображается экран «Список контактов» с добавленным контактом. На экране «Пустой контакт» пользователь может отменить ввод нового контакта. В этом случае экран «Список контактов» отображается без сохранения контакта. Экран «Пустой контакт» показан на рисунке 3 слева внизу.
Рисунок 3. Экраны пустого контакта (слева) и существующего контакта (справа).
В «Списке контактов» пользователь также может выбрать существующий контакт и просмотреть его данные на экране «Существующий контакт», как показано на рисунке 3 справа вверху. Здесь пользователь может отредактировать контакт и сохранить изменения, после чего пользователь возвращается к экрану «Список контактов» с обновленной контактной информацией. В «Существующем контакте», если выбрано «Отмена», пользователь возвращается в «Список контактов», и в контактную информацию не вносятся никакие изменения. Экран «Существующий контакт» идентичен «Пустому контакту», за исключением того, что контактные данные заполнены существующей контактной информацией.
В «Существующем контакте» пользователь также может нажать кнопку «Удалить», чтобы удалить контакт. При нажатии кнопки «Удалить» появляется экран «Подтвердить удаление», рисунок 4 ниже. В «Подтверждение удаления», если нажата кнопка «Удалить», контакт удаляется, и пользователь возвращается на экран «Список контактов». В «Подтверждение удаления», если нажата кнопка «Отмена», никаких действий не предпринимается, и пользователь возвращается к экрану «Существующий контакт».
Рисунок 4. Подтвердите удаление экрана.
При переходах по экрану, которые требуют определенного объема обработки данных, приложение отображает экран «Ход выполнения» в режиме ожидания пользователя (рис. 5 ниже). Экран хода выполнения всегда отображается перед отображением любого из экранов «Создание учетной записи», «Список контактов», «Пустой контакт» и «Существующий контакт».
Рисунок 5. Экран прогресса.
Подводя итог обсуждению выше, на следующем рисунке показан поток экрана в нашем приложении.
Рисунок 6. Поток экрана.
Структура мобильной страницы jQuery
Давайте обсудим, как будут отображаться экраны в нашем приложении с помощью элементов страницы jQuery Mobile. (Подробное обсуждение того, как страницы создаются в платформе jQuery Mobile, см. В разделе справочной документации « Анатомия страницы» .) Один HTML-файл в платформе jQuery Mobile состоит из одной страницы контейнера с одной или несколькими страницами содержимого внутри контейнера. , Страница контейнера имеет атрибут data-role="page"
тогда как страницы содержимого имеют атрибут data-role="content"
. Страница содержимого может дополнительно иметь верхний и нижний колонтитулы. В приведенном ниже примере есть две страницы содержимого с верхним и нижним колонтитулами и одна страница содержимого без верхнего или нижнего колонтитула.
01
02
03
04
05
06
07
08
09
10
11
12
|
<div data-role=»page»>
<div data-role=»header»>…</div>
<div id=»contentWithHeaderAndFooter1″ data-role=»content»>…</div>
<div data-role=»footer»>…</div>
<div data-role=»header»>…</div>
<div id=»contentWithHeaderAndFooter2″ data-role=»content»>…</div>
<div data-role=»footer»>…</div>
<div id=»contentWithNoHeaderAndFooter» data-role=»content»>…</div>
</div>
|
На странице контейнера он предназначен для одновременного отображения только одной страницы содержимого. Идея состоит в том, чтобы сгруппировать логически связанные экраны вместе на одной странице контейнера и определить каждый из них как страницу контента. Например, эти страницы контента могут иметь общий код JavaScript. Другим примером является тот, где главная страница контента группируется вместе с несколькими другими страницами контента, которые представляют диалоги, связанные с основным контентом.
В этом учебном приложении каждый из экранов «Создание учетной записи» (рисунок 1), «Список контактов» (рисунок 2) и «Ход выполнения» (рисунок 5) представлен в виде страницы содержимого на странице контейнера, которая хранится на физической странице ListPage.html
. Аналогично, физическая страница DetailPage.html
содержит страницу контейнера с тремя страницами содержимого; одна из этих страниц содержимого используется для представления экранов «Пустой контакт» и «Существующий контакт» (рисунок 3), другая страница содержимого представляет экран «Подтверждение удаления» (рисунок 4), а третья страница содержимого представляет экран «Ход выполнения». Следующий рисунок суммирует это обсуждение.
Рисунок 7. Структура страницы.
Отображение / скрытие содержимого страниц выполняется программно. Это будет показано во время просмотра кода ниже.
Интеграция пользовательского интерфейса на основе HTML / JavaScript с бэкэндом Android Java
В этом руководстве мы разрабатываем собственное Android-приложение, в котором пользовательский интерфейс реализован на основе jQuery Mobile, который состоит из библиотек JavaScript и CSS. Фреймворк jQuery Mobile призван помочь в разработке мобильных веб-приложений с единообразным пользовательским интерфейсом для различных мобильных платформ, устройств и браузеров. Как таковой, он не имеет специального механизма интеграции, например, плагина, с Android из коробки. По этой причине интеграция jQuery Mobile с Android должна быть разработана на заказ.
Прежде чем приступить к рассмотрению HTML-страниц и JavaScript, а также Java-кода этого руководства, имеет смысл рассмотреть три основных аспекта этой интеграции:
- Доступ к Java из JavaScript
- Доступ к HTML / JavaScript из Java
- Типы данных параметров в вызовах методов между Java-JavaScript
Доступ к Java из JavaScript
Android предоставляет общий способ представления объектов Java Java Android в коде JavaScript с помощью addJavascriptInterface(Object object, String interfaceName)
в классе android.webkit.WebView
. По сути, этот метод позволяет вызывать открытые методы объекта Java из кода JavaScript, запущенного в WebView
. Обратите внимание, что WebView
— это особый вид android.view.View
созданный на основе WebKit и позволяющий отображать веб-страницы, состоящие из HTML и JavaScript. Находятся ли они в Интернете или упакованы вместе с собственным приложением Android, эти веб-страницы имеют ссылки через URL-адреса, чтобы WebView
мог их найти и отобразить. (Заинтересованный читатель может обратиться к исходной документации API для получения дополнительной информации о WebView
и View
.)
На рисунке ниже показано, как осуществляется доступ к Java-объекту с помощью кода JavaScript, выполняющегося в WebView
где HTML-страница является частью пакета приложений Android. Объект Java доступен для кода JavaScript как объект JavaScript.
Рисунок 8. Java — привязка JavaScript.
В приведенном ниже примере показано, как представить объект Java, экземпляр класса ContactsActivity
, как объект JavaScript. В Activity.onCreate()
мы сначала инициализируем экземпляр WebView
. Затем объект ContactsActivity
регистрируется как объект JavaScript под именем contactSupport
. Класс ContactsActivity
имеет различные открытые методы, например deleteContact()
.
импорт android.webkit.WebView; импорт android.app.Activity; ... открытый класс ContactsActivity расширяет Activity { WebView webView; ... public void onCreate (BundlevedInstanceState) { ... webView = новый WebView (это); ... webView.addJavascriptInterface (this, <B> "contactSupport" </ B>); ... } public void <B> deleteContact </ B> (String contactId, String displayPage) { ... }
Приведенный ниже фрагмент кода показывает пример доступа к объекту ContactsActivity
из кода JavaScript. Это так же просто, как вызов любого открытого метода объекта с использованием зарегистрированного имени объекта.
<Скрипт> ... function someJavaScriptFunction () { .. <B> contactSupport.deleteContact </ b> (contactIdVar.val (), 'ListPage.html'); } ... </ Скрипт>
Доступ к HTML / JavaScript из Java
В этом учебном приложении мы будем использовать loadUrl(String url)
в классе WebView
для двух разных целей: (1) загрузить новую страницу HTML в WebView
и (2) вызвать метод JavaScript на текущей загруженной странице HTML в WebView
. Если рассматривать их в перспективе с помощью контейнера jQuery Mobile и страниц контента, мы придерживаемся следующих правил.
- Переход с одной страницы содержимого на другую внутри той же страницы контейнера выполняется кодом JavaScript.
- Переход с одной страницы контейнера на другую выполняется с помощью кода Java с использованием
WebView.loadUrl(String url)
. Отображаемая страница контейнера передается в код Java из JavaScript в качестве параметра обратного вызова.
Помимо загрузки новой HTML-страницы, метод WebView.loadUrl(String url)
также используется для вызова метода JavaScript на загруженной в данный момент HTML-странице. Метод вызова JavaScript передается в Java в качестве параметра обратного вызова из кода JavaScript. Для любого метода JavaScript, который вызывает метод Java, диаграмма ниже суммирует взаимодействие между Java и JavaScript.
- При стимулировании пользователя или загрузке HTML-страницы код JavaScript сначала отображает экран хода выполнения.
- Затем код JavaScript выполняет некоторую обработку данных в зависимости от конкретной области и вызывает метод Java. Метод Java передает параметры для обработки (необязательно) и либо функцию JavaScript для обратного вызова, либо HTML-страницу для загрузки после того, как метод Java завершает обработку своей бизнес-логики.
- Метод Java завершает обработку своей бизнес-логики, а затем вызывает функцию JavaScript или загружает страницу HTML в соответствии с запросом.
Рисунок 9. Java — JavaScript-взаимодействие.
Теперь давайте посмотрим, как код Java реализует эти взаимодействия.
Загрузка HTML-страниц через WebView
В приведенном ниже листинге кода приведен пример метода Java deleteContact()
. Эта функция вызывается JavaScript с идентификатором контакта, который нужно удалить, и именем HTML-страницы, которая должна отображаться после удаления контакта. (Идентификатор контакта является уникальным идентификатором этого контакта в базе данных контактов устройства Android.)
импорт android.webkit.WebView; импорт android.app.Activity; импорт android.os.Handler; ... открытый класс ContactsActivity расширяет Activity { WebView webView; закрытый обработчик обработчика = ноль; ... public void onCreate (BundlevedInstanceState) { ... webView = новый WebView (это); ... обработчик = новый обработчик (); ... } public void deleteContact (String contactId, String displayPage) { ContactUtility.deleteContact (ContactId, ...); loadPage (displayPage); } public void loadPage (String in) { final String url = "file: /// android_asset / www /" + in; loadURL (URL); } private void loadURL (последняя строка в) { handler.post (new Runnable () { public void run () { webView.loadUrl (в); } }); }
Во-первых, давайте посмотрим, как мы используем android.os.Handler
. Ссылка на Android для android.view.View
гласит:
«… Вы всегда должны быть в потоке пользовательского интерфейса при вызове любого метода в любом представлении. Если вы выполняете работу над другими потоками и хотите обновить состояние представления из этого потока, вам следует использовать обработчик».
Для нас это означает, что метод deleteContact()
не может напрямую вызывать WebView.loadUrl()
. Это из-за двух причин. Во-первых, экземпляр WebView
создается в onCreate()
. Во-вторых, когда метод deleteContact()
вызывается из JavaScript, поток, который выполняет этот метод, отличается от потока, который выполнил метод onCreate()
ContactsActivity
. Это видно из ссылки Android на WebView.addJavascriptInterface()
где говорится «… Java-объект, связанный (с JavaScript), выполняется в другом потоке, а не в потоке, в котором он был создан».
Это где android.os.Handler
полезно. Из ссылки на Android объект Handler
позволяет нам выполнить действие WebView.loadUrl()
в данном случае WebView.loadUrl()
) в определенном потоке, который связан с объектом Handler
. В onCreate()
мы инициализируем оба WebView
и Handler
и поэтому оба этих объекта связаны с одним и тем же потоком.
Учитывая эту концепцию Handler
, приведенный выше список теперь должен быть понятен.
- В
deleteContact()
мы сначала удаляем контакт (классContactUtility
будет рассмотрен позже). - Затем мы вызываем метод
loadPage()
который просто ставит префикс перед именем отображаемой HTML-страницы, преобразуя имя страницы в URL-адресfile://
. - Наконец, мы вызываем метод
loadURL()
чтобы объектHandler
вызывалWebView
.
Вызов методов JavaScript через WebView
Рассмотрев пример, в котором код Java отображал HTML-страницу после обработки запроса, давайте рассмотрим другой пример, где код Java вызывает метод JavaScript после обработки запроса, чтобы передать его результаты обратно.
открытый класс ContactsActivity расширяет Activity { ... public void <B> getAllContacts </ B> (обратный вызов строки, обратный вызов строки) { final String accountCallbackFunction = "javascript:" + accountCallback + "()"; if (accountName == null) { loadURL (accountCallbackFunction); возвращение; } final String json = ContactUtility.getAllContactDisplaysJSON (getContentResolver ()); final String callbackFunction = "javascript:" + callback + "('" + json + "')"; loadURL (callbackFunction); }
Метод getAllContacts()
генерирует список всех контактов в формате JSON и передает результат обратно в указанную функцию JavaScript обратного вызова. Методу передаются два имени функции обратного вызова JavaScript. Первый должен использоваться для передачи списка контактов. Второй используется только после первоначальной установки, когда учетная запись для учебного приложения еще не создана. Вызов этой второй функции JavaScript должен помочь пользователю создать учетную запись.
Список JavaScript-кода, вызывающий метод ContactsActivity.getAllContacts()
приведен ниже.
<Скрипт> $ (документ) .ready (function () { ... . ContactSupport <B> getAllContacts </ b> ( 'setContactsList', 'showAccount'); }); </ Скрипт>
Функция setContactsList()
функция, которая берет список контактов в формате JSON, анализирует его и отображает экран «Список контактов» на рисунке 2 выше. Функция showAccount()
отображает экран «Создание учетной записи» на рисунке 1 без какой-либо обработки данных. Мы предоставим обзор этих функций позже.
Типы данных параметров в вызовах методов
В этом приложении мы используем тип данных String только во время вызовов функций между JavaScript и Java. Другие примитивы, такие как Integer, передаются как String и затем приводятся к нужному типу. Сложные типы объектов также сериализуются в форматированную строку JSON, а затем анализируются обратно в объект на принимающей стороне.
На стороне Java мы используем JSON Processor Jackson для преобразования туда и обратно между объектами данных Java и строковыми представлениями этих объектов в формате JSON. Что касается JavaScript, то для анализа строки в формате JSON мы используем метод jQuery.parseJSON () . С другой стороны, генерирование строки в формате JSON в JavaScript выполняется программно. При дальнейшем рассмотрении приведенного ниже кода эти функциональные области будут описаны более подробно.
Запуск приложения
Класс ContactsActivity
является android.app.Activity
и точкой входа в наше учебное приложение. Подробнее о классе Android Activity
см. Http://developer.android.com/guide/topics/fundamentals.html . Класс ContactsActivity
также является внутренним интерфейсом Android, который используется кодом JavaScript на HTML-страницах, представляющих пользовательский интерфейс.
Когда наше учебное приложение загружается, вызывается метод ContactsActivity.onCreate()
.
пакет com.jquerymobile.demo.contact; открытый класс ContactsActivity расширяет Activity { WebView webView; закрытый обработчик обработчика = ноль; private String accountType = null; private String accountName = null; ... public void onCreate (BundlevedInstanceState) { super.onCreate (savedInstanceState); // Инициализируем WebView webView = новый WebView (это); setContentView (WebView); // Включить JavaScript webView.getSettings () setJavaScriptEnabled (истина). // Проверяем наличие аккаунта для этого приложения accountType = "com.jquerymobile.demo.contact"; Account [] accounts = AccountManager.get (this) .getAccountsByType (accountType); if (accounts.length! = 0) { accountName = account [0] .name; } обработчик = новый обработчик (); // Привязать этот объект как объект JavaScript webView.addJavascriptInterface (this, "contactSupport"); // Загрузка index.html loadPage ( "index.html"); } ... }
Важные шаги в onCreate()
заключаются в следующем:
- Мы инициализируем экземпляр
WebView
и разрешаем ему запускать JavaScript. - Каждый контакт, созданный нашим приложением, должен быть связан с
android.accounts.Account
. Мы будем использовать учетную запись, специфичную для нашего приложения. Тип приложенияcom.jquerymobile.demo.contact
, названный в честь пакета приложения. Используя классandroid.accounts.AccountManager
, мы ищем, есть ли учетная запись этого типа. Если это так, мы инициализируем полеaccountName
с этим именем. - Мы инициализируем поле
handler
. - Экземпляр
ContactsActivity
привязан к JavaScript как объект под именемcontactSupport
. - Наконец, мы загружаем файл
index.html
вWebView
. Это единственный HTML-файл с жестко заданным именем в нашем коде Java. Имена всех других файлов HTML передаются методамContactsActivity
качестве параметров.
Список для index.html
приведен ниже. Все, что делает этот файл — это вызывает в функции jQuery $(document).ready()
метод ContactsActivity.loadPage()
передавая 'ListPage.html'
в качестве параметра. В результате WebView
загружает ListPage.html
.
index.html
<HTML> <Голова> <link rel = "stylesheet" href = "css-js / jquery.mobile-1.0a3.min.css" /> <script src = "css-js / jquery-1.5.min.js"> </ script> <script src = "css-js / jquery.mobile-1.0a3.min.js"> </ script> </ HEAD> <Тело> ... <Скрипт> $ (документ) .ready (function () { contactSupport.loadPage ( 'ListPage.html'); }); </ Скрипт> </ Body> </ Html>
Начальная загрузка ListPage.html
ListPage.html
содержит три страницы содержимого (см. Рисунок 7). Они соответствуют экранам «Создание учетной записи» и «Список контактов» на рисунках 1 и 2, соответственно, и экрану «Ход выполнения», например, показанному на рисунке 5. Вспомните из предыдущего обсуждения, что в любой данный момент будет отображаться только одна из этих страниц. время.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
<html>
<head>
<B><!— jQuery Mobile Libraries —></B>
<link rel=»stylesheet» href=»css-js/jquery.mobile-1.0a3.min.css» />
<script src=»css-js/jquery-1.5.min.js»></script>
<script src=»css-js/jquery.mobile-1.0a3.min.js»></script>
</head>
<body>
<B><!— Container Page —></B>
<div data-role=»page» data-theme=»c» id=»containerPage»>
<B><!— Contact List —></B>
<div data-role=»header» id=»hdrList» data-nobackbtn=»true»>
<h1><img align=»top» src=»img/contacts.png»> Contacts</h1>
<a id=»buttonAddContact» data-icon=»plus» class=»ui-btn-right»
href=»<B>javascript:addContact();</B>return false;»
</div>
<div data-role=»content» id=»contentList» data-theme=»c»>
<ul data-role=»listview» data-dividertheme=»c» id=»contactSelections»></ul>
</div>
<div data-role=»footer» id=»ftrList»></div>
<B><!— Progress —></B>
<div data-role=»header» id=»hdrProgress» data-nobackbtn=»true» data-theme=»c»>
<h1>Processing…</h1>
</div>
<div data-role=»content» id=»contentProgress» data-theme=»c»>
<div align=»CENTER»><h4>Please wait.</h4></div>
<div align=»CENTER»><img id=»spin» src=»img/wait.gif»/></div>
</div>
<div data-role=»footer» id=»ftrProgress» data-theme=»c»></div>
<B><!— Create Account —></B>
<div data-role=»header» id=»hdrAccount» data-nobackbtn=»true» data-theme=»c»>
<h1>Create Account</h1>
</div>
<div data-role=»content» id=»contentAccount» data-theme=»c»>
<div align=»CENTER»><img src=»img/contacts-master-bgd.png»></div>
<div align=»CENTER»><h4>Please enter name of the new account for this application</h4></div>
<div align=»CENTER»>Contacts created with this application will be associated with the new account specified below.
Other contacts can be viewed, however, cannot be deleted or modified with this application.</div>
<div align=»CENTER» id=»accountDiv» data-role=»fieldcontain»>
<input id=»accountName» type=»text» />
</div>
<div align=»CENTER»>
<a href=»javascript:createAccount();return false;»
data-inline=»true»</B>>Save</a>
</div>
…
</div>
<div data-role=»footer» id=»ftrAccount» data-theme=»c»></div>
</div> <B><!— Container Page Ends Here —></B>
…
|
Пожалуйста, обратите внимание на следующее.
- На всех трех страницах контента определены разделы верхнего и нижнего колонтитула. Все эти разделы имеют
data-theme="c"
которая определяет конкретную цветовую тему, доступную в jQuery Mobile. Для получения подробной информации, пожалуйста, смотрите оригинальную ссылку на jQuery Mobile Theme Framework . - По умолчанию jQuery Mobile размещает кнопку «Назад» в разделе заголовка. Мы контролируем навигацию в нашей программе и поэтому не нуждаемся в кнопке возврата. В результате мы устанавливаем
data-nobackbtn="true"
. (Для получения дополнительной информации о навигационной модели jQuery Mobile см. Исходную ссылку на эту тему.) - Раздел заголовка в «Списке контактов» имеет кнопку «Добавить», которая вызывает метод JavaScript с именем
addContact()
который будет рассмотрен позже. Первоначально «Список контактов» состоит из пустого списка,id="contentList"
, который будет программно заполняться на основе данных из серверной части Java. - На экране «Создать учетную запись» есть кнопка для сохранения имени учетной записи как введенного пользователем. Обратите внимание на
data-inline="true"
в определении этой кнопки. Это означает, что кнопка должна обернуться вокруг текста «Сохранить». Без этого кнопка будет заполнять ширину экрана по умолчанию. Подробнее см. Документацию по jQuery Mobile для встроенных кнопок .
Мы продолжаем изучать ListPage.html
. В приведенном ниже списке показано, как отобразить один из экранов «Создание учетной записи», «Список контактов» и «Ход выполнения». В функции jQuery $(document).ready()
мы инициализируем несколько переменных, представляющих разделы заголовка, содержимого и нижнего колонтитула страниц содержимого для этих экранов, используя селектор идентификатора $('#...')
. Затем определите функции « hide Page ()
, « show Page ()
для каждой страницы содержимого. Например, showList()
отображает экран «Список контактов» и скрывает экраны «Создание учетной записи» и «Ход выполнения».
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
<script>
…
// Commonly used variables
…
var hdrListVar;
var contentListVar;
var ftrListVar;
var hdrProgressVar;
var contentProgressVar;
var ftrProgressVar;
var hdrAccountVar;
var contentAccountVar;
var ftrAccountVar;
$(document).ready(function () {
// Initialize commonly used variables
hdrListVar = $(‘#hdrList’);
contentListVar = $(‘#contentList’);
ftrListVar = $(‘#ftrList’);
hdrProgressVar = $(‘#hdrProgress’);
contentProgressVar = $(‘#contentProgress’);
ftrProgressVar = $(‘#ftrProgress’);
hdrAccountVar = $(‘#hdrAccount’);
contentAccountVar = $(‘#contentAccount’);
ftrAccountVar = $(‘#ftrAccount’);
…
});
…
function hideList(){
hdrListVar.hide();
contentListVar.hide();
ftrListVar.hide();
}
function showList(){
hideProgress();
hideAccount();
hdrListVar.show();
contentListVar.show();
ftrListVar.show();
}
function hideProgress(){
hdrProgressVar.hide();
contentProgressVar.hide();
ftrProgressVar.hide();
}
function showProgress(){
hideList();
hideAccount();
hdrProgressVar.show();
contentProgressVar.show();
ftrProgressVar.show();
}
function hideAccount(){
hdrAccountVar.hide();
contentAccountVar.hide();
ftrAccountVar.hide();
}
function showAccount(){
hideList();
hideProgress();
hdrAccountVar.show();
contentAccountVar.show();
ftrAccountVar.show();
}
…
</script>
|
Выделенный раздел ниже дает остаток функции $(document).ready()
в ListPage.html
. Отображается экран хода выполнения, и через привязку JavaScript вызывается метод ContactsActivity.getAllContacts()
. setContactsList
передаются два параметра: setContactsList
— это имя функции обратного вызова JavaScript для использования списка контактов в формате JSON. Второй параметр, showAccount
, является функцией обратного вызова JavaScript, которая showAccount
, если в данный момент для этого приложения не настроена учетная запись. Обе эти функции обратного вызова находятся в ListPage.html
, текущем физическом файле.
$ (документ) .ready (function () { // Инициализируем часто используемые переменные hdrListVar = $ ('# hdrList'); contentListVar = $ ('# contentList'); ftrListVar = $ ('# ftrList'); hdrProgressVar = $ ('# hdrProgress'); contentProgressVar = $ ('# contentProgress'); ftrProgressVar = $ ('# ftrProgress'); hdrAccountVar = $ ('# hdrAccount'); contentAccountVar = $ ('# contentAccount'); ftrAccountVar = $ ('# ftrAccount'); <B> ShowProgress (); contactSupport.getAllContacts ( 'setContactsList', 'showAccount'); </ b> });
ContactsActivity
Ответы
В приведенном ниже списке ContactsActivity.getAllContacts()
метод ContactsActivity.getAllContacts()
.
public void getAllContacts (обратный вызов строки, обратный вызов строки) { final String accountCallbackFunction = "javascript:" + accountCallback + "()"; if (accountName == null) { loadURL (accountCallbackFunction); возвращение; } final String json = ContactUtility.getAllContactDisplaysJSON (getContentResolver ()); final String callbackFunction = "javascript:" + callback + "('" + json + "')"; loadURL (callbackFunction); }
Мы частично рассмотрели этот код раньше. Подведем итог:
- Если в настоящее время для этого приложения не создана учетная запись, вызывается функция обратного вызова JavaScript для экрана «Создание учетной записи». Это делается через
loadURL(accountCallbackFunction)
. - Если у приложения есть учетная запись,
ContactUtility.getAllContactDisplaysJSON()
вызывается для получения отформатированного в JSON списка контактов на устройстве. Результирующая строка JSON передается в функцию обратного вызова JavaScript для отображения этих контактов. Это делается черезloadURL(callbackFunction)
. - Пример строки в формате JSON для списка контактов приведен ниже. Контакты сгруппированы в алфавитном порядке по первому инициалу их отображаемых имен. Каждая группа идентифицируется атрибутом
key
, значением которого является буква, представляющая группу, и состоит из массива контактов внутри группы с именованнымиvalues
. Каждый элемент массива имеетcontactId
иdisplayName
. Элементы в массиве далее сортируются в алфавитном порядке на основеdisplayName
. (В разделе «Получение списка контактов в формате JSON» ниже приведен обзор кода, генерирующего этот список.)
{ "контакты": [ { "ключ": "ценность", "A": [ {"contactId": "257", "displayName": "Aach Herb", "key": "A"}, ..., {"contactId": "256", "displayName": "Aaker David", "key": "A"} ] }, { "ключ": "В", "ценности": [ {"contactId": "259", "displayName": "Belanger Andre", "key": "B"}, ..., {"contactId": "260", "displayName": "Bohme Jacob", "key": "B"} ] }, ... ] }
Экран создания аккаунта
Когда метод ContactsActivity.getAllContacts()
вызывает функцию JavaScript showAccount()
в ListPage.html
, пользователю показывается экран «Создание учетной записи» на рисунке 1.
Экран списка контактов
Если для приложения существует учетная запись, функция обратного вызова setContactsList()
в ListPage.html
будет анализировать строку списка контактов в формате JSON и отображать контакты для пользователя. Список этой функции приведен ниже.
.. <div data-role = "content" id = "contentList" data-theme = "c"> <ul data-role = "listview" data-dividertheme = "c" id = "<B> contactSelections </ B>"> </ ul> </ DIV> ... <Скрипт> ... // Обычно используемые переменные ... <B> var contactSelectionsVar; </ B> $ (документ) .ready (function () { // Инициализируем часто используемые переменные ... <B> contactSelectionsVar = $ ('# contactSelections'); </ B> ... } ... function setContactsList (jsonText) { var tmpJson = $ .parseJSON (jsonText); if (tmpJson! = null && tmpJson.contacts! = null) { var tmpContacts = tmpJson.contacts; для (i = 0; i <tmpContacts.length; i ++) { var tmpKey = (tmpContacts [i]). key; var tmpKeyFragment = '<li data-role = "list-divider">' + tmpKey + '</ li>'; <B> contactSelectionsVar.append (tmpKeyFragment); </ b> var tmpValues = (tmpContacts [i]). values; if (tmpValues! = null) { вар j; для (j = 0; j <tmpValues.length; j ++) { var tmpDisplayName = tmpValues [j] .displayName; var tmpContactId = tmpValues [j] .contactId; var tmpLiFragment = '<li> <a href = "javascript: showContact (' + tmpContactId + '); вернуть false; ">' + tmpDisplayName + '</a> </ li>'; <B> contactSelectionsVar.append (tmpLiFragment); </ b> } } } } <B> contactSelectionsVar.listview ( 'Обновить'); </ b> showList (); } ... </ Скрипт>
- Функция jQuery parseJSON вызывается для анализа строки JSON и возврата полученного объекта JavaScript.
- Напомним, что контакты организованы в группы на основе первого инициала их displayName.Для каждой группы
tmpKey
переменнойkey
присваивается значение атрибута группы, значением которого является буква, представляющая группу. - Затем эта
tmpKey
переменная используется для создания разделителя мобильного списка jQuery , который представляется в виде строковой переменной с именемtmpKeyFragment
. Каждый разделитель списка обозначает начало новой группы и несет букву, представляющую группу. - Переменная
contactSelectionsVar
является указателем на пустой список сid="contactSelections"
. ИспользуяjQuery.append()
функцию, мы добавляем разделитель списка в этот список. - Следующим шагом является чтение массива контактов в группе, доступ к которому осуществляется через
values
атрибут, определенный в строке JSON. Из каждого элемента массива мы извлекаемdisplayName
иcontactId
атрибуты и сохраняем их в переменныхtmpDisplayName
иtmpContactId
, соответственно. - Переменные
tmpDisplayName
иtmpContactId
используются для создания другой переменнойtmpLiFragment
, которая представляет отдельный элемент списка для контакта. Этот элемент списка добавляется к списку, указанному указателемcontactSelectionsVar
. - Наконец, мы обновляем список контактов через,
contactSelectionsVar.listview('refresh')
чтобы обновить вид списка. Откроется экран «Список контактов» на рисунке 2. - На рисунке ниже показано, как фрагменты кода выше помогают построить список контактов.
Рисунок 10. Построение списка контактов.
Заключительные замечания к части 1 этого урока
В этой начальной части учебного курса мы представили цели учебного пособия и обсудили пример приложения, которое будет реализовано. Мы также дали обзор элементов страницы в jQuery Mobile Framework и объяснили, как экраны в примере приложения построены с использованием этих элементов. Мы также рассмотрели основные концепции интеграции пользовательского интерфейса, состоящего из HTML и JavaScript, с внутренними классами Java, которые реализуют бизнес-функциональность.
Во второй части мы продолжим обучение, демонстрируя, как создать учетную запись для вновь созданных контактов. Мы также опишем, как редактировать и удалять существующие контакты.