html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

PhoneGap: как сделать приложение отзывчивым

На сегодняшний день существует немалое количество обзорных статей о PhoneGap, но к сожалению, написаны они или front-end разработчиками, которые решили заняться мобильными платформами, или нативными программистами, которые решили попробовать себя в кроссплатформенной разработке. И именно с этих позиций рассматриваются достоинства и недостатки PhoneGap'а, возникают статьи о том, «насколько крута кроссплатформа», или об «ущербности кроссплатформенных решений».

В качестве затравки — видео демо-приложения, написанного за 6 часов; готовым был взят UI-бутстрап, наверстанный за 3,5 часа; использовались библиотеки iScroll, backbone, underscore, Jquery, и небольшая обертка на backbone (RAD.js — rapid application development, архитектурный фреймворк, берущий на себя часть оптимизации, связанной с мобильной средой выполнения).


Еще 2 часа было потрачено на фикс движка. Но сегодня речь не о том, что что-то тормозит, дергается, или самописный свайп не всегда вовремя отрабатывает на 14000 объектах данных; речь о том, что на PhoneGap можно и нужно писать.

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

PhoneGap позиционируется как платформа для кроссплатформенной разработки на HTML/JavaScript под семь мобильных операционных платформ.

Кроссплатформенность в PhoneGap достигается тем, что код Вашего HTML/JavaScript-приложения выполняется в компоненте webView (представляющего собой, встроенный в приложение браузер).

Фактически разработка PhoneGap-приложения представляет собой разработку HTML5-приложения с учетом особенностей среды выполнения (мобильное устройство, ограниченная процессорная мощность, память, тачскрин и т.д.) и… зоопарка браузеров.
Точно так, как при разработке под десктопные браузеры, при разработке мобильных сайтов или PhoneGap-приложений Вам необходимо знать и учитывать специфику каждой операционной системы и ее дефолтного браузера, на базе которого построен компонент webView.

И главное, на что влияет ограниченность мобильной среды выполнения PhoneGap-приложения и ресурсов, — это отзывчивость пользовательского интерфейса.

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

Поэтому мы в своих программах пытаемся акцентировать внимание на отзывчивости пользовательского интерфейса. И в данный статье не будем говорить об оптимизации JavaScript-кода или CSS, так как это не специфично для PhoneGap и мобильных приложений, и, кроме этого, об этом уже немало написано(тут, тут, тут или тут).

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

Статьи, которые комплексно рассматривают взаимосвязь интерфейса и отзывчивости мобильного веб-приложения, найти непросто. Для примера можно привести эту статью, или же эту. Вторая статья достаточно свежая, и указывает направление «движения» для создания хорошего приложения на PhoneGap, но автор в ряде случаев использует «canvas based UI», что не всегда возможно).
Но и в этих статьях, к сожалению, рассмотрены не все проблемы.

Выделим проблемы, которые мы считаем характерными, и которые хотели бы рассмотреть сегодня:

  • Задержка в 300 миллисекунд события «click» на «тач»-устройствах;
  • Проблема касания
  • Оптимизация DOM-структуры;
  • Проблема больших списков.


Возможно в чем-то мы повторимся, но всеже начнем.

Проблема задержки в 300 мсек:

Большинство мобильных операционных систем в своем браузере (и как следствие, в webView) для решения проблемы ложных касаний вводят специальную задержку около 300 миллисекунд между непосредственным нажатием и запуском события «click» в DOM'e.

Подход к решению этой проблемы нетрудно найти на просторах интернета. Существует как минимум несколько десятков JavaScript-библиотек, решающих эту проблему. Принцип действия всех их одинаков — отслеживать события «touchstart» и «touchend» — и в момент окончания последнего вызывать событие «click» или аналогичное кастомное (например, «tap»). Примеры можно найти и как решение на stackoverflow, и как плагин к JQuery, и как отдельную библиотеку, причем даже в реализации от Mozilla или просто в качестве советов.

К сожалению, всегда есть небольшое «но» — если генерировать событие «click» (например, как советует компания google в своем решении), то через некоторую задержку Вам придется отловить и прекратить распространение стандартного «click», сгенерированного самим браузером. Что в старых версиях android может привести к несовместимости со сторонними библиотеками. При этом, если генерировать кастомное событие, то фокус будут передаваться с задержкой, и эта задержка будет видна при выборе полей ввода.

Найти же библиотеку, которая корректно передает и устанавливает фокусы при клике для элементов, и в то же время корректно работает с различными типами полей ввода, достаточно трудно и впридачу она будет довольно объемной. Намного проще и безболезненней использовать общепринятый подход — генерировать не событие «click», а другое любое кастомное событие — и подвязывать слушателя непосредственно к нему.

И хотя, в этом случае Ваше приложение и становится зависимым от данной библиотеки, этот недостаток с лихвой перекрывается простотой решения и наименьшим количеством багов.
Следует также предостеречь Вас от привязки отдельных экземпляров «fastclick» на каждый элемент UI, так как делают некоторые библиотеки. Это решение, хоть и работоспособное, но крайне затратное с точки зрения потребления ресурсов мобильного устройства. Необходимо использовать делегирование и привязку, например, на «body» слушателя и генерацию всплывающего кастомного события по координатам нативного.

Вторая проблема — точка касания:

Еще одна часто встречающаяся проблема в неправильно спроектированных интерфейсах мобильных устройств (в том числе и на PhoneGap) звучит из уст пользователей так: «я нажимаю, а оно не всегда срабатывает» или «я нажимаю, а оно не работает».
Давайте внимательно рассмотрим следующий рисунок, отображающий, как именно происходит взаимодействие пальца пользователя с экраном устройства.

image

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

Именно по этим причинам, реальная точка касания никогда не совпадет с визуальной.

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

Исправляется этот момент достаточно просто — грамотной версткой элементов управления приложения; например, когда кнопка имеет невидимый падинг в 4-6 пикселей если она недостаточно большая по дизайну: то есть ее бэкграунд имеет невидимые внешние границы, которые увеличивают ее физический размер до необходимого и удобного пользователю (розовое поле на рисунке).

image

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

А теперь о самом нетривиальном — об оптимизации DOM-структуры


image


Если посмотреть на более-менее «стандартный» экран «среднего» приложения, то можно насчитать от 200-300 html тегов (узлов DOM), с помощью которых наверстан экран приложения. В данном конкретном примере страница наверстана с помощью 225 HTML-элементов. Далеко, не самая оптимальная верстка, но, как бы мы ни старались, в любом случае, в среднем экране PhoneGap-приложения можно насчитать от 100 до 250 элементов HTML. И попросим учесть, что мы пока не рассматриваем экраны со списками (об этом поговорим чуть-чуть позже).

Среднее приложение, аналогичное нативному, содержит от пяти до полутора десятков экранов. В случае PhoneGap, все эти старницы являются частью single-page приложения.

Существует общепринятый подход к архитектуре такого приложения: все страницы верстаются в одном html файле как блоки, а потом, в ходе выполнения программы, в зависимости от того, какая страница необходима, стилями
display: none;
display: block;

отображается нужная страница (так, например, делается в JqueryMobile ).

Но этот подход, к сожалению, приводит к задержкам в приложении при переключении страниц(и не только). И чем сложнее приложение, тем длительнее эти задержки.

Связано это с тем, что даже для самой обычной JavaScript-функции запроса к DOM, например, document.querySelector('selector'), время выполнения зависит от количества узлов в объектной модели документа. К примеру, указанная операция при трехуровневом селекторе выполняется за 0.003 мсек при 100 элементах и 0.36 мсек при 10000 элементах (ориентировочно 40 страниц приложения). Можно возразить, что это мелочи: 40 страниц не часто встречаются в реальной жизни, да и 0.36 мсек — копейки.

Но чистым JavaScript никто никогда практически не пользуется, а при использовании JQuery(до 2 версии) указанное время вырастает до 2.46 мс. А если учитывать, что кроме простого запроса необходимо также провести какие-либо манипуляции с DOM, то это уже может привести к заметным даже на глаз задержкам в достаточно сложном приложении.

Приведем небольшой СИНТЕТИЧЕСКИЙ тест, генерирующий документ с различным количеством элементов, и выводящий результат выборки двухуровнего CSS в консоль.

Результат его выполнения на Chrome 28.0.1500.63
start create 1 items index.js:12
none 1 items: 0.078ms index.js:38
none jquery 1 items: 0.774ms index.js:43
block 1 items: 0.131ms index.js:38
block jquery 1 items: 0.234ms index.js:43
jquery show1 items: 1.768ms index.js:52
start create 10 items index.js:12
none 10 items: 0.071ms index.js:38
none jquery 10 items: 0.138ms index.js:43
block 10 items: 0.139ms index.js:38
block jquery 10 items: 0.090ms index.js:43
jquery show10 items: 0.865ms index.js:52
start create 100 items index.js:12
none 100 items: 0.071ms index.js:38
none jquery 100 items: 0.099ms index.js:43
block 100 items: 0.103ms index.js:38
block jquery 100 items: 0.105ms index.js:43
jquery show100 items: 1.418ms index.js:52
start create 1000 items index.js:12
none 1000 items: 0.178ms index.js:38
none jquery 1000 items: 0.163ms index.js:43
block 1000 items: 0.156ms index.js:38
block jquery 1000 items: 0.176ms index.js:43
jquery show1000 items: 9.709ms index.js:52
start create 10000 items index.js:12
none 10000 items: 2.333ms index.js:38
none jquery 10000 items: 2.434ms index.js:43
block 10000 items: 1.810ms index.js:38
block jquery 10000 items: 1.810ms index.js:43
jquery show10000 items: 106.425ms

Как видно из теста, решение с «display: none» не помогает, так как это убирает работу только по отрисовке документа, но не меняет времени при запросах к «избыточному» DOM.
Это решение помогает нам избавиться только от reflow и repaint, поведение браузера при этих событиях великолепно рассмотрено в статье.

Еще раз напоминаем, что тест синтетический, не соответствующий реальным условиям, и некоторые позиции были специально «завалены». Но он прекрасно дает представление, что может произойти в реальном проекте с single-page приложением при большом количестве страниц и сложной верстке.

И хотя, время будет различаться на различных платформах (в различных браузерах), нетрудно увидить, что в мобильных браузерах ситуация будет еще хуже — в сложных одностраничных приложениях со стандартным подходом вы вряд ли получите плавную анимацию на мобильном устройстве.

В этом случае есть два варианта решения:

  • Грузить содержимое страниц ajax-запросами;
  • Если страница уже наверстана стандартным подходом, после ее загрузки в DOM нужно отсоединить ветви DOM, отвечающие за невидимые страницы от основного дерева DOM, сохранив ссылки на эти ветви в JavaScript (например с помощью api.jquery.com/detach/), в этом случае GC не очистит отсоединенные ветви.


image


Максимальной же оптимизации можно добиться, комбинируя эти два варианта. Тогда загружать страницу или шаблон Вам прийдется только в первый раз, в дальнейшем просто присоединяя или отсоединяя DOM ветви к основному дереву документа.

Не следует также забывать и об известных местах оптимизации.

И снова о DOM — проблема больших списков

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

В нативных компонентах это реализовано через кэш (пример реализации нативного компонента на Android).


image


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

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

В качестве решения данной проблемы можно порекомендовать «пейджинацию», то есть отображение списка по частям. Данное архитектурное решение реализуют множество js-библиотек; его можно очень красиво обыграть — например, свайпом.

image

Или же можно написать или найти JavaScript-библиотеку, реализующую функциональность аналогичную нативным компонентам; например, как сделано в InfiniteWall или здесь.

Напоследок хотелось бы дать несколько полезных советов, которые, как мы надеемся, помогут Вам сэкономить время и нервы:

  1. Чем меньше сторонних библиотек Вы используете, тем лучше, связано это с ограниченными ресурсами мобильного устройства. Для сравнения могу привести эскадру из «звездолетов» — сторонних библиотек. Вы хотите, чтобы эта эскадра перевезла один-единственный «груз» — выполнила бизнес-кейс Вашего приложения. Но топливо будет потреблять вся эскадра. Поэтому экономьте ресурсы (Ваше «топливо»), выбирайте библиотеки наиболее оптимально и пытайтесь наиболее полно использовать их возможности. К примеру, JQuery, начиная с версии 2, не на много уступает в производительности zepto, а функциональности намного больше.
  2. Ваше приложение совсем не обязательно должно выглядеть одинаково на всех платформах и версиях ОС. Возможно, стоит пойти на некоторые уступки в стилях и оформлении, чтобы сохранить быстродействие и функциональность программы. Вспомните ситуацию с IE;
  3. В списках не используйте атрибут «src» для тегов img, используйте CSS background для вывода изображения; в этом случае изображение будет подгружено только в том случае, если элемент списка виден на экране;
  4. Не всегда методы оптимизации, работающие в случае веб-страниц с клиент-серверной архитектурой, важны и оптимальны для приложения на PhoneGap. Например, нет смысла обращать внимание на на размер загружаемого JavaScript-файла или на минимизацию невидимых пикселей в изображении, так как в нашем случае нет долгих сетевых запросов для загрузки этих файлов. К сожалению, задержку в 250 миллисекунд перед загрузкой каждого файла никто не отменял, и Вам решать, как с этим бороться. Мы для себя выбрали ленивую предзагрузку и тайлы;
  5. Располагайте поля ввода в верхней части экрана — это позволит избежать различного поведения верстки страницы при отображении клавиатуры на мобильных устройствах;
  6. Избегайте больших списков — это сложная задача; беритесь за нее, когда у Вас уже есть хотя бы наметки для ее решения;
  7. Избавляйтесь по максимуму от теней, градиентов и полупрозрачности. Вся эта красота требует дополнительной мощности от мобильного устройства, поэтому используйте это только там, где действительно необходимо;
  8. Используйте мощность графического процессора через CSS, например так:
    transform: translate3d(0,0,0); -webkit-transform: translate3d(0,0,0);
    В частности, можно почитать о конкретной реализации.
    Или более подробно с тестами.


И еще несколько ссылок на статьи с советами: тут, тут или тут.

Но самое главное, что мы хотим сказать: На PhoneGap'e можно писать.

Хотя он не является панацеей для разработки. Каждый инструмент предназначен для своих задач. С помощью PhoneGap можно написать отзывчивое приложение и/или приложение с нестандартным дизайном (причем это даже легче сделать, чем при реализации нативным кодом). Но если Вам нужна обработка больших объемов данных, то скорее всего, PhoneGap Вам не подойдет, хотя иногда и с этим можно бороться.

Надеемся наши советы пригодятся.

P.S. Спустя 11 часов оптимизации UI баги остались, с теми же размерами кнопок, но приложению реально «полегчало».
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

2

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • habrahabr.ru
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции