Опубликован: 10.04.2013 | Доступ: свободный | Студентов: 440 / 9 | Длительность: 16:52:00
Специальности: Программист
Лекция 1:

Командный пользовательский интерфейс

Лекция 1: 123456 || Лекция 2 >

Улучшение обработки ошибок в "Here My Am!"

Для того, чтобы завершить эту лекцию и свести воедино большую часть того, о чем мы говорили, внесем некоторые изменения в "Here My Am!". В последний раз мы работали над этой программой, улучшая обработку различных ошибок. В ее теперешнем состоянии программа ведет себя не очень хорошо. А именно, есть сложности в следующих областях:

  • Если загрузка скрипта элемента управления карт Bing из удаленного источника не удается, код в html/map.html просто выдает исключение и программа завершается.
  • Если мы используем приложение на мобильном устройстве и изменили наше местоположение, нет способа обновить отметку на карте другим способом кроме ручного перетаскивания маркера. Таким образом, API для определения местоположения используется лишь при старте программы.
  • Когда API определения местоположения WinRT пытается получить сведения о местоположении и при этом нет сетевого соединения, возникают паузы в несколько секунд, когда пользователь не может знать, что происходит.
  • Если при попытке воспользоваться API определения местоположения вызов не удастся, обычно из-за тайм-аута или проблем с сетевым соединением, но так же – возможно из за-того, что пользователь это запретил, нет способа попробовать выполнить то же действие еще раз.

Приложение "Here My Am!" (7) для этой лекции учитывает эти вопросы. Во-первых, я добавил изображение, которое должно выводиться при ошибке, в html/map.html (изображение находится по адресу html/maperror.png), таким образом, если не удается загрузить скрипт карт Bing, вместо карты будет выведено изображение (в этом случае стиль отображения none будет удален):

<img id="errorImage" style="display: none; width: 100%; height: 100%;" src="maperror.png" /> 

Кроме того, я добавил к изображению обработчик события click, который перезагружает содержимое iframe с document.location.reload(true). Когда это сделано, я могу убрать исключения, которые возникли ранее, когда карта не могла быть создана, предотвращая аварийное завершение приложения. Вот как выглядит ситуация, когда карта не может быть создана:


Для того, чтобы протестировать такой вариант развития событий, вам нужно отключиться от Интернет, деинсталлировать приложение (для очистки кэшированных скриптов карты; в противном случае карта, все равно, будет загружаться!) и снова запустить приложение. Ошибка должна произойти в начале метода init в файле html/map.html, что приведет к появлению изображения путем удаления стиля по умолчанию display: none и подключения обработчика click . Затем снова подключитесь к Интернету и нажмите на изображение. Карта должна перезагрузиться, но если проблема с соединением сохранилась, снова появится изображение, сигнализирующее об ошибке.

Вторая проблема – добавление возможности обновлять наше местоположение – просто решаема с помощью панели приложения. Я добавил такой элемент управления на страницу default.html с одной командой:

<div id="appbar" data-win-control="WinJS.UI.AppBar" data-win-options="">
<button data-win-control="WinJS.UI.AppBarCommand"	
data-win-options="{id:'cmdRefreshLocation', label:'Refresh location',
icon:'globe', section:'global', tooltip:'Refresh your location'}">
</button>	
</div>
 

Эта команда подключена внутри pages/home/home.js в методе ready элемента управления страницы:

var appbar = document.getElementById("appbar").winControl;
appbar.getCommandById("cmdRefreshLocation").addEventListener("click", this.tryRefresh.bind(this));
 

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

tryRefresh: function () {	
//Скрыть панель приложения и попробовать снова	
var appbar = document.getElementById("appbar").winControl.hide();
this.refreshPosition();	
},
 

Мне так же понадобилось настроить функцию pinLocation в html/map.html. Без команды обновления местоположения, эта функция вызывалась лишь однажды, при запуске приложения. Так как теперь она может быть вызвана много раз, нам нужно удалить любые существующие метки на карте, прежде чем добавлять метку для нового местоположения. Это делается путем вызова map.entities.pop перед уже существующим вызовом map.entities.push, который отмечает новое местоположение.

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


Что касается третьей проблемы – дать пользователю знать о том, что приложение пытается получить данные о местоположении – мы можем показать маленькое всплывающее сообщение сразу же после попытки вызова getGeopositionAsync из WinRT. Всплывающий элемент, определенный в pages/home/home.html (в нашем элементе управления страницы) центрирован вдоль нижней части области карты:

<div id="retryFlyout" data-win-control="WinJS.UI.Flyout" aria-label="{Trying geolocation}"
data-win-options="{anchor: 'map', placement: 'bottom', alignment: 'center'}">	
<div class="win-type-large">Attempting to obtain geolocation...</div>	
</div>
 

Функция refreshFunction которую мы только что добавили в pages/home/home.js является отличным местом для отображения всплывающего окна сразу перед вызовом getGeopositionAsync:

 refreshPosition: function () {
document.getElementById("retryFlyout").winControl.show(); 
var gl = new Windows.Devices.Geolocation.Geolocator();

gl.getGeopositionAsync().done(function (position) {
//...

//Всегда скрывать всплывающий элемент document.getElementById("retryFlyout").winControl.hide();

//...
}, function (error) {
//...

//Всегда скрывать всплывающий элемент	
document.getElementById("retryFlyout").winControl.hide();
});	
},

Обратите внимание на то, что мы скрываем всплывающий элемент внутри обработчиков ошибки и завершения, поэтому сообщение остается видимым во время проведения асинхронной операции. Если мы разместим одну команду, скрывающую всплывающий элемент, за пределами этих обработчиков, сообщение будет отображаться лишь очень короткое время перед закрытием, а это – не то, что нам нужно. Когда мы это написали, у пользователя будет достаточно времени для того, чтобы увидеть сообщение вдоль нижней части карты (если только он не решит закрыть его):


Последняя задача заключается в том, чтобы сообщить пользователю о том, что при попытке получить сведения о местоположении произошла ошибка. Мы можем сделать это с помощью еще одного всплывающего элемента с кнопкой Retry (Повторить), или во встроенном сообщении, как показано ниже. Нам не следует пользоваться в этом случае диалоговым окном сообщения, так как сообщение появляется в ответ на действие пользователя, которым он запускает процесс обновления данных. Окно сообщения допустимо использовать при запуске программы, но с помощью встроенного сообщения, скомбинированного со всплывающим элементом мы уже выполнили все, что нужно.

Для встроенного сообщения, я добавил плавающий элемент div, который позиционирован примерно на трети расстояния от верхнего края карты. Он определен в defined/home/home.html, как показано, в качестве элемента одного уровня с iframe:

<div id="locationSection" class="subsection" aria-label="Location section">	
<h2 class="group-title" role="heading">Location</h2>	
<iframe id="map" class="graphic" src="ms-appx-web:///html/map.html"	
aria-label="Map"></iframe>	
<div id="floatingError" class="win-type-x-large">Unable to obtain geolocation;<br />
use the app bar to try again.</div>	
</div>
 

Стиль для правила #floatingError в pages/home/home.css задает внешний вид и расположение элемента:

#floatingError { 
display: none; float: left;
-ms-grid-column: 1;
-ms-grid-row: 2;
-ms-grid-row-align: start;
width: 100%;
text-align: center;
background-color: rgba(128, 0, 0, 0.5);
margin-top: 20%;
}
 

Так как этот элемент размещен в той же ячейке сетки, что и карта со стилем float, это выглядит как хорошо выглядящее наложение:


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

С параметром display: none в CSS, сообщение об ошибке первоначально скрыто, как это и должно быть. Если мы попадаем в обработчик ошибки для getGeolocationAsync , мы устанавливаем style.display в значение block , что отображает элемент:

document.getElementById("floatingError").style.display = "block"; 

Мы снова скрываем сообщение внутри функции tryRefresh, которая вызывается посредством команды на панели приложения, таким образом, сообщение остается скрытым, если ошибка повторяется:

tryRefresh: function () {	
document.getElementById("floatingError").style.display = "none";
//...	
},
 

Так же мы можем добавить окно сообщения, если мы обнаружим, что сетевое соединение потеряно, и, таким образом, не можем обновить местоположение. Как мы увидим в лекции 3 курса "Программная логика приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript и их взаимодействие с системой", это можно сделать с помощью события Windows.Networking.NetworkInformation.onnetworkstatuschanged ( http://msdn.microsoft.com/library/windows/apps/windows.networking.connectivity.networkinformation.networkstatuschanged.aspx). В подобном случае вполне можно воспользоваться окном сообщения, так как происходящее не связано с непосредственными действиями пользователя.

Кроме того, стоит отметить, что если бы мы использовали элемент управления из Bing Maps SDK в данном приложении, скрипт, который мы загружаем из удаленного источника, хранился бы в пакете нашего приложения, таким образом, устраняя причину первой ошибки. Мы внесем это изменение в следующую версию программы

Что мы только что изучили

  • В дизайне приложений для Магазина Windows, команды, которые имеют отношение к рабочему процессу, следует располагать на полотне приложения или во всплывающих меню элементов, например – заголовка. Те команды, которые могут быть размещены в интерфейсе чудо-кнопки Параметры, нужно размещать там; это значительно упрощает реализацию приложения. Те команды, которые остались, обычно отображаются на панели приложения или на панели навигации. Панели могут содержать всплывающие меню для некоторых командных элементов. Контекстные меню (Windows.UI.Popups.PopupMenu ) так же можно использовать для команд, связанных с содержимым.
  • Элемент управления WinJS.UI.Flyout используется для подтверждений и других вопросов, которые отображаются в результате действий пользователя. Они так же могут просто выводить сообщения, собирать дополнительную информацию или предоставлять элементы управления для изменения настроек некоторых частей страниц. Неактивные всплывающие элементы могут быть скрыты, то есть, щелчок или прикосновение за пределами элемента или нажатие на клавишу Escape приводит к их скрытию, что равносильно нажатию на кнопку Отмена (Cancel) в ответ на вопрос, который может быть задан в подобном элементе.
  • Диалоговые окна сообщений (Windows.UI.Popups.MessageDialog ) используются для задавания вопросов, на которые пользователь должен ответить, или вывода информации, с которой он обязательно должен ознакомиться, прежде чем приложение сможет продолжить работу. Окно сообщения блокирует приложение. Окна сообщений лучше всего использовать для вывода сведений об ошибках или условиях, которые воздействуют на приложение в целом. Сообщения об ошибках, которые относятся к содержимому странице, следует показывать на странице.
  • Панель приложения – это элемент управления WinJS, на котором можно располагать стандартные команды, используя командный макет, или любой HTML-код, который вам нужен, с использованием пользовательского макета. Возможно использование пользовательских значков, можно использовать различные шрифты или пользовательские изображения. Приложение может иметь и верхнюю и нижнюю панели, где верхняя обычно используется для целей навигации и применяет пользовательский макет. Панели приложения могут отображаться в режиме залипания для того, чтобы оставаться видимыми, а не скрываться, если они не активны.
  • Методы панели приложения showCommand , hideCommand и showOnlyCommand , вместе со свойством команд extraClass , упрощают описание панели приложения в одном месте приложения и выборочный показ конкретных наборов команд с использованием querySelectorAll с классом, который представляет данный набор.
  • Командные меню, появляющиеся у команд панели приложения, или вызываемые различными элементами управления, расположенными на полотне, реализованы с помощью элемента управления WinJS.UI.Menu .
  • В качестве примера использования многих из этих возможностей, в данной лекции обновлено приложение "Here My Am!", что привело к значительному улучшению обработки ошибок в этом приложении.
Лекция 1: 123456 || Лекция 2 >
Вадик Елетин
Вадик Елетин
Россия, г. Санкт-Петербург
Николай Жигульский
Николай Жигульский
Россия, Тверь, Тверской государственный технический университет