412 000 произведений, 108 200 авторов.

Электронная библиотека книг » Иво Салмре » Программирование мобильных устройств на платформе .NET Compact Framework » Текст книги (страница 42)
Программирование мобильных устройств на платформе .NET Compact Framework
  • Текст добавлен: 18 июля 2025, 02:31

Текст книги "Программирование мобильных устройств на платформе .NET Compact Framework"


Автор книги: Иво Салмре



сообщить о нарушении

Текущая страница: 42 (всего у книги 69 страниц)

Тестирование на эмуляторах и физических устройствах

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

(Их особенно "любит" охрана в аэропортах.) Вместе с тем, для чего эмуляторы совершенно не годятся – так это для тестирования производительности вашего мобильного приложения или удобства работы с его пользовательским интерфейсом. В связи с этим вы должны тестировать свои приложения только на физических устройствах. Как бы вы ни старались, результаты тестирования, полученные с использованием эмулятора, не могут считаться надежными. Ниже приводится несколько причин того, почему это так.

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

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

■ Размеры вашей руки никак не учитываются при работе с компьютерным экраном. При использовании эмулятора для элементов управления пользовательского интерфейса трудно подобрать наиболее оптимальное расположение, поскольку курсор мыши имеет очень небольшие размеры и не закрывает экран при его перемещении над кнопками. Курсор мыши вообще физически ни с чем не связан. В отличие от этого перо, используемое совместно с сенсорным экраном, имеет заметные размеры и физически связано с вашей рукой, которая имеет еще большие размеры; поэтому, когда вы пытаетесь надавить на кнопку, вы непроизвольно закрываете значительную часть экрана.

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

■ Эмулятор можно легко сбросить, и он не используется для других целей в промежутках между выполнением тестовых запусков вашего приложения. Эмулированный смартфон – это вовсе не тот самый телефон, который вы используете для телефонных переговоров и ведения расписания встреч. Тот факт, что физическое устройство часто предназначается не только для определенного способа его использования, но и для выполнения других функций, имеет очень большое значение. Вам необходимо убедиться в нормальной работе приложения в условиях, когда устройство функционирует в течение 24 часов 7 дней в неделю, а также попытаться понять, каким образом другие приложения, выполняющиеся на устройстве, могут влиять на ваше приложение. Добиться точной имитации такого рода реальных условий эксплуатации приложения очень трудно.

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

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

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

Рис. 13.3.  Сравнение удобства использования пользовательского интерфейса на эмуляторе и физическом устройстве

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

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

Рис. 13.4. Более удобные альтернативные варианты компоновки экрана, основанные на результатах тестирования приложения на физическом устройстве 

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

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

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

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

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

2. Использование косвенных функций для обновления пользовательского интерфейса. Изменение информации, отображаемой на экране мобильного устройства, может осуществляться двумя способами: 1) непосредственно, путем использования встроенного кода (например, Label1.Text = newText) и 2) косвенно (например, UpdateDownloadStatusText(newText);). Преимущество косвенного подхода заключается в том, что он позволяет вашему коду отделить фактически используемый элемент управления от того обновления, которое вы хотите выполнить. Косвенная функция UpdateDownloadStatusText(newText); сегодня может обновлять элемент Label1, но, возможно, завтра вы решите, что лучше будет отобразить текст поверх растрового изображения или вывести его в виде текста, прокручиваемого в узкой полоске экрана. На рис 13.5 показана стрелка, направленная вниз от пользовательского интерфейса (ПИ) к блоку функций обновления ПИ, а также стрелки, направленные вверх от блока логики приложения. Стрелка, направленная вниз от пользовательского интерфейса, представляет код обновления дисплея, который выполняется в результате обработки событий, генерируемых пользовательским интерфейсом. Например, обычной реакцией на щелчок на кнопке может быть обновление текста в ярлыке или окне списка. Вместо того чтобы выполнять это обновление непосредственно в обработчике событий кнопки, можно поступить гораздо более гибко и воспользоваться вызовом обобщенной функции UpdateXXXXXXX(), которая и выполнит всю работу. Введение промежуточной функции позволяет разорвать прочную связь между обоими элементами управления и при необходимости использовать другую реализацию одного из них. Проектируя пользовательский интерфейс своего мобильного приложения, вы должны избегать тесного связывания как элементов управления с логикой приложения, так и отдельных элементов управления, являющихся частью пользовательского интерфейса, между собой. Наличие единственного уровня косвенности позволяет устранить такое тесное связывание.

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

Рис. 13.5. Надежное отделение логики приложения от пользовательского интерфейса

Модель состояний для компоновки пользовательского интерфейса и управления им

Чтобы проиллюстрировать плодотворность концепции пользовательского интерфейса, управляемого конечным автоматом, целесообразно привести простой пример. Этот пример продемонстрирует эффективность подхода, основанного на конечном автомате, как фактора, облегчающего внесение изменений в пользовательский интерфейс по мере эволюции проекта. В продолжение сценариев, иллюстрируемых рисунками 13.3, 13.4 и 13.5, код рассматриваемого примера реализует основные компоненты пользовательского интерфейса приложения для Pocket PC, предназначенного для изучения в игровой форме слов иностранного языка. По мере того как пользователь приложения отвечает на вопросы, выбирая правильный, по его мнению, ответ из нескольких предложенных вариантов, в секторе игрового поля осуществляются некоторые действия, соответствующие тому, какой ответ был дан пользователем – правильный или неправильный.

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

Как показано на рис. 13.6, пользовательский интерфейс мобильного приложения имеет четыре состояния:

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

2. Формулировка вопроса. В этом состоянии мобильное приложение предлагает пользователю перевести предложенное слово. В нашем коде мы решили отображать вопрос в элементе управления TextBox, но это вовсе не является обязательным. Например, вопрос может отображаться в элементе управления Label или выводиться поверх растрового изображения игрового поля, если оно имеется. Если целевое устройство поддерживает синтезатор речи, то вопрос может задаваться даже голосом. Мы решили использовать текстовое поле, работающее в режиме только для чтения, поскольку его возможности нас полностью устраивают и позволяют без труда отображать большие объемы информации за счет использования полос прокрутки, если это потребуется. В дополнение к отображению вопроса приложение предлагает пользователю выбрать один из двух способов ответа на него. Пользователь может выбрать вариант Challenge Me! (Ну-ка, спрашивай!), если считает, что знает правильный ответ, или Can't Think of It (Ума не приложу), если нуждается в дальнейших подсказках; для каждого из этих двух вариантов выбора могут быть предусмотрены различные правила подсчета очков. Чтобы не усложнять пробный код, в нашей реализации оба варианта обрабатываются по одному и тому же принципу и перемещают пользователя в следующее состояние приложения независимо от того, какой вариант был выбран; возможно, вы захотите добавить код, который будет по– разному подсчитывать очки для этих вариантов, или просто исключите одну кнопку, если решите этого не делать. В нашей реализации мобильного приложения для представления обоих вариантов было решено использовать элементы управления Button, но, как и ранее, такое решение не является обязательным; точно так же для предоставления этих вариантов выбора можно использовать переключатели или выпадающий список, если эти метафоры являются более подходящими для целевого устройства. Какую метафору пользовательского интерфейса выбрать, зависит от природы приложения, а также от типа устройства, на котором оно будет выполняться.

3. Предоставление пользователю нескольких вариантов ответа. В этом состоянии приложения наша игра для мобильных устройств предлагает пользователю несколько вариантов ответа на заданный ему вопрос. Для пользовательского интерфейса Pocket PC мы вновь решили использовать элементы управления Button; для смартфонов более подходящими были бы, пожалуй, нумерованные окна списков. Кроме того, в этом состоянии мы решили динамически уменьшать размер элемента управления TextBox, чтобы кнопки всех вариантов выбора уместились на экране. Пользователи могут угадывать правильный ответ до тех пор, пока он не будет получен. В нашей реализации в случае выбора неправильного ответа соответствующая кнопка затеняется (для ее свойства Enabled устанавливается значение false). В логику нашего приложения также можно включить код для отображения того, что в действительности означает неверно выбранное вами слово. Поскольку, в силу ограниченности размеров текстового окна, для отображения этой информации места недостаточно, мы могли бы вывести этот текст поверх растрового изображения игрового поля; этот вариант реализации мы также оставляем на усмотрение читателя.

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

Представленный в листинге 13.1 код демонстрирует несколько полезных концепций построения гибких пользовательских интерфейсов мобильных устройств. Проектируя этот пользовательский интерфейс, я начал с идеи размещения элементов поверх игрового поля. Зная, что окончательный выбор подходящего пользовательского интерфейса определится лишь после его тестирования в реальных условиях и внесения соответствующих изменений, при написании кода было желательно использовать принципы централизации и абстрагирования кода таким образом, чтобы процесс его модифицирования не вызывал особых затруднений и не заставлял вносить сложные изменения в разных местах кода пользовательского интерфейса или логики приложения. Именно поэтому я решил поместить основную часть кода динамической компоновки в функцию конечного автомата, которая называется StateChangeForGameUI(). Любые изменения размеров или позиционирование элементов управления управляются этим кодом. Если нам необходимо немного подправить компоновку элементов или даже радикально изменить ее, мы знаем, что все необходимое осуществляется здесь; благодаря этому снижается объем работы по отслеживанию сложной и разбросанной по всему коду логики компоновки, а приложение становится более надежным. Возложив всю ответственность за поддержание компоновки пользовательского интерфейса на одну функцию (конечный автомат), мы значительно облегчили выполнение экспериментов с различными возможными вариантами компоновки, поскольку теперь это не сможет дестабилизировать работу остальной части кода пользовательского интерфейса и логики приложения.

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

Рис. 13.6. Отображение пользовательского интерфейса в верхней части формы

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

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

Рис. 13.7. Отображение пользовательского интерфейса в нижней части формы

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

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


    Ваша оценка произведения:

Популярные книги за неделю