Основные UI паттерны разработки Android приложений
Поскольку разработка приложений под Android набирает популярность, думаю обзор основных UI паттернов для Android-приложений будет кому-то полезен. Основой для статьи является вот этот вот источник. Рассматриваемые паттерны: Dashboard, Action Bar, Quick Actions, Search Bar и Companion Widget.
На мой взгляд тема UI паттернов является важной по нескольким причинам:
- Привлечение пользователей: паттерны помогают сделать приложение более юзабильным, более понятным.
- Проход на рынок: следование паттернам может сыграть важную роль при продвижении приложения на app market’ы.
- Не стоит строить велосипед: при знании паттернов намного проще заниматься проектированием интерфейса приложения, используя имеющиеся решения.
Принципы дизайна интерфейса, отмеченные инженерами Google:
- Simple vs Clear: интерфейс должен быть простым(не нагруженным) и понятным для использования
- Content vs Chrome: необходимо использовать максимум экрана, при этом уменьшать его визуальную сложность (использовать ограниченное число кнопок/иконок)
- Consistent yet engaging: консистентность реакции пользователя – пользователь должен понимать что он делает/как сделать то, что ему необходимо
- Enhanced by cloud: данные пользователя следует хранить в облаке; пользователь должен иметь возможность выбирать настройки(организовывать данные) один раз, без повторных действий.
UI Design Patterns(по аналогии с Software Design Patterns) описывают общее решение для повторно возникаемых задач/проблем и возникают как “побочный продукт” процесса разработки.
Ниже перечислены пять UI паттернов с примерами на основе всем известного приложения.
DashBoard
Dashboard (Панель инструментов) – представляет описание основных возможностей приложения, является главным меню приложения. Dashboard занимает весь экран, фокусируется на 3-6 наиболее важных функциях приложения, также может содержать информацию об обновлениях.
Поскольку паттерн Dashboard по сути является лицом приложения, подходить к его разработке нужно особенно аккуратно.
Action Bar
Action Bar предоставляет быстрый доступ к дополнительным функциям приложения, является наилучшим решением представления функций, используемых из любой точки приложения(поиск, синхронизация, рефреш и т.п.).
Action Bar не является полноценной заменой меню, но содержит ключевые действия, которые пользователь может выполнить(пользователь не должен входить в меню для выполнения этих действий). При этом паттерн не должен содержать контекстуальных действий(таких как копировать/вставить) Action Bar может также использоваться для ориентирования пользователя в приложении(а именно, показывать ему где он находится).
Quick Actions
Quick Actions – предоставляет доступ к контекстуальным функциям приложения, вызывается при клике на ”цели”, выводится на эран в качестве popup. Ключевые характеристики Quick Actions: действия должны соответствовать контексту, быть простыми и понятными(возможно использование иконок), действий не должно быть много. Стоит также отметить, что всплывающий popup не должен перекрывать “цели”(должен появляться либо снизу, либо сверху по отношению к “цели”). Использовать данный паттерн рекомендуется когда нет детального описания item-a, а также когда в приложении необходимо выполнить дополнительные действия, связанные с контекстом. Quick Actions не следует использовать, когда доступен мультиселект.
Search Bar
Search Bar – используется для поиска по приложению (заменяет Action Bar). Search Bar должен поддерживать предложения по поиску, а также может содержать селектор для выбора типа поиска.
Рекомендации по реализации паттерна: следует использовать для простого поиска по приложению, представлять богатые предложения поиска(например, заголовок с иконкой и описанием).
Companion Widget
Companion Widget – виджет, представляет основную информацию о приложении, может быть настроен пользователем. Кроме иконки должен иметь содержание(описание, значек апдейта, возможно некоторые функции приложения), должен сохранять пространство рабочего стола, а также предоставлять пользователю возможность настройки вида виджета.
Инженеры Google рекомендуют уделять больше внимания этому элементу интерфейса, поскольку он играет важное значение во взаимодействии с пользователем. Простой ярлык приложения – не самое лучшее решение.
Рассмотренные паттерны являются базовыми при разработке Android приложений, однако это не значит что все их обязательно необходимо применять. Главной все же остается идея, исходя из которой можно рассматривать различные варианты решений( это к тому что, разрабатывать все же стоит от идеи, а не от паттерна).
Удачи вам в реализации ваших идей!
Источник
Архитектура Android-приложений. Часть II — архитектурные стили и шаблоны
В этой статье мы поговорим об архитектурных шаблонах, используемых в Android-приложениях.
Почему важно понимание шаблонов, реализованных в рамках некой архитектуры? Потому что таким образом изучаемая нами новая архитектура укладывается в контекст нашего предыдущего опыта и позволяет нам более эффективно использовать накопленные знания и навыки.
Возможно, я плохо искал, но в документации Android нет упоминания о каких-либо шаблонах. Не смотря на это, в Android реализованы некоторые шаблоны и архитектурные стили, о которых мы сейчас и поговорим.
Архитектура Android является фреймворк-ориентированной (framework-based), в противовес вольной (free-style) архитектуре.
В чём разница? Вольные приложения, написанные на Java, начинаются с класса, имеющего метод main(), и разрабатываются в полном соответствии с настроением разработчика.
В противоположность этому фреймворк-ориентированные приложения основываются на существующем фреймворке. Их разработка сводится к расширению неких классов или реализации интерфейсов, предоставленных фрейморком. Такое приложение не может быть запущено вне фреймворка или без него. Примером могут быть веб-приложения на Java, в которых разработчики реализуют интерфейс Servlet или расширяют одну из его реализаций, или приложения Eclipse RCP, в котором разработчик расширяет один из классов Editor или View.
Фреймворк-ориентированная архитектура ограничивает свободу разработчиков, предписывая им что и как следует делать. Но, в итоге, исчезают повторяющиеся участки кода (boilerplate code), и разработчикам приходится (хотелось бы в это верить) тщательно следовать шаблонам проектирования.
Для Java существует множество фреймворков. Тем не менее, команда Android решила создать свой собственный. Возможно, одной из причин, по которой они так поступили, была необходимость поддерживать уникальную систему управления памятью.
В «обычной» Java объекты находятся в памяти до тех пор, пока сборщик мусора не доберётся до них. Происходит это только тогда, когда на объект нет ни одной ссылки от «живых» объектов (подробнее можно почитать здесь). В Android это не так. Если некий интерфейс пользователя скрывается (то есть он более не видим на экране), то нет никакой гарантии, что он находится в памяти, даже есть приложение в дальнейшем собирается использовать его. Если у ОС Android есть достаточно свободной памяти, эти объекты могут храниться в ней, но сборщик мусора может уничтожить их в любой момент, когда ОС решит, что памяти осталось слишком мало. То же верно и для процессов. Процесс, который в данный момент времени не показывает пользователю никакого графического интерфейса, может быть уничтожен ОС Android на абсолютно законных основаниях (есть одно исключение из этого правила — сервисы; об этом мы поговорим позже).
Рассмотрим пример. Пусть наше приложение имеет экраны A и B. Пользователь сначала открывает экран A, а затем экран B; с этого момента экран A стал невидим. Это означает, что экран A и вся логика, содержащаяся в нём, может находиться в памяти, а может и не находиться. Так, нет гарантий, что объекты, связанные с экраном A находятся в памяти, пока виден экран B. Логика экрана B не должна завязываться на нахождение объектов экрана A в памяти. Побочный эффект состоит в том, что архитектура Android принуждает к использованию архитектурного стиля стиля «shared nothing». Это означает, что разные части Android приложения могут вызывать друг друга и взаимодействовать между собой только формально; ни один из них не может обратиться к другому напрямую.
Хорошо, а что случится, если пользователь решит вернуться на экран A? Наверное, он захочет увидеть его в том же состоянии, в котором он оставил его, верно? Вот как фреймворк Android решает эту проблему: для каждого состояния жизненного цикла существуют методы, каждый из которых может быть переопределён разработчиком. Эти методы вызываются фреймворком в заранее определённые ключевые моменты, например, когда пользовательский интерфейс показывается на экране, прячется и т.п. В этих методах разработчик может реализовать логику для хранения и восстановления состояния объектов.
Подобная обработка скрытия пользовательских интерфейсов и существование кнопки «назад» на Android-устройствах приводит к необходимости наличия стека пользовательских интерфейсов, в котором текущий видимый интерфейс помещается на вершину, а все остальные сдвигаются вниз (стековая операция «push»). Нажатие «назад» удаляет интерфейс с вершины стека и показывает элемент, который был за ним (стековая операция «pop»). Подобный стек существует в Android. В документации он называется «activity stack» или иногда «back stack».
В плане обработки взаимодействия между пользовательским интерфейсом и его логикой Android следует архитектурному шаблону «Model-View-ViewModel» (MVVM). Для разработчиков это хорошая новость, поскольку MVVM — самая лучшая архитектура GUI-приложений на настоящий момент.
Архитектура MVVM была создана с целью разделения труда дизайнера и программиста, которое невозможно, когда Java-разработчик пытается построить GUI в Swing или разработчик на Visual C++ пытается создать пользовательский интерфейс в MFC. Разработчики — сообразительные парни и имеют множество навыков, но создание удобных и привлекательных интерфейсов требует абсолютно других талантов, нежели те, которыми они обладают разработчики. Эта работа больше подходит для дизайнеров интерфейсов. Хорошие дизайнеры интерфейсов лучше знают, чего хотя пользователи, нежели эксперты в области проектирования и написания кода. Понятно, будет лучше, если дизайнер интерфейсов создаст интерфейс, а разработчик напишет код, который реализует логику этого интерфейса, но технологии типа Swing или MFC просто-напросто не позволяют поступать таким образом.
Архитектура MVVM решает эту проблему ясным разделением ответственности:
- Разработка пользовательского интерфейса совершается дизайнером интерфейсов с помощью технологии, более или менее естественной для такой работы (XML)
- Логика пользовательского интерфейса реализуется разработчиком как компонент ViewModel
- Функциональные связи между пользовательским интерфейсом и ViewModel реализуются через биндинги (bindings), которые, по сути, являются правилами типа «если кнопка A была нажата, должен быть вызван метод onButtonAClick() из ViewModel». Биндинги могут быть написаны в коде или определены декларативным путём (Android использует оба типа).
Архитектура MVVM используется в том или ином виде всеми современными технологиями, например Microsoft WPF и Silverlight, Oracle JavaFX, Adobe Flex, AJAX.
Мы упоминали, что различные части Android-приложения могут вызывать друг друга и взаимодействовать между собой только формально. Как же это достигается? Фреймворк Android использует несколько шаблонов взаимодействия:
- Обмен сообщениями с помощью класса Intent
- Наблюдатель с использованием классов Intent и BroadcastReceiver
- Позднее связывание с последующим вызовом метода используется для доступа к контент-провайдерам (ContentProviders) и локальным (внурипроцессным) сервисам (Services)
- Позднее связывание и межпроцессное взаимодейтсвие (Inter-process Procedure Communication, IPC) для вызова сервисов (AIDL)
Не волнуйтесь, если что-то из этого звучит непонятно. Подробные объяснения будут в следующих статьях.
Источник
Применяем паттерны проектирования в Android. Flyweight
Тема паттернов проектирования будет актуальная всегда, потому что писать масштабируемый и читаемый код нужно всегда, независимо под какую платформу вы проектируете. Поэтому в этом посте мы на примере рассмотрим паттерн проектирования Flyweight, он же Легковес или Приспособленец. Итак для чего используется этот паттерн?
Легковес — это структурный паттерн проектирования, который позволяет вместить бóльшее количество объектов в отведённую оперативную память. Легковес экономит память, разделяя общее состояние объектов между собой, вместо хранения одинаковых данных в каждом объекте.
Пример
Рассмотрим мобильное приложение для поиска недвижимости. Скорее всего в такого типа приложении один из экранов для поиска будет состоять из карты и множества маркеров, обозначающих квартиру или дом. Если таких объектов будет очень много, например, больше 100 000 то, учитывая ограниченные ресурсы мобильного телефона, приложение может начать подтормаживать, из-за нехватки оперативной памяти.
Решение
В этом случае нам может помочь
- Кластеризация
- Использование паттерна Flyweight.
Паттерн Легковес предлагает не хранить в классе внешнее состояние, а передавать его в те или иные методы через параметры. Таким образом, одни и те же объекты можно будет повторно использовать в различных контекстах. Но главное — понадобится гораздо меньше объектов, ведь теперь они будут отличаться только внутренним состоянием, а оно имеет не так много вариаций.
А где используется?
Помните, в начале поста был вопрос, что будет в случае сравнения двух чисел 127?
В этом случае сравнение вернет результат true и тест будет пройден. Однако в случае сравнения 128 результат будет false и тест провалится.
Все дело в том, что используя == мы сравниваем ссылки по которым эти объекты хранятся. Когда мы пишем Integer a = 127 мы создаем Integer (ссылочный тип). Получается что сравнивая a == b мы сравниваем ссылки двух объектов. Но почему-то для 127 результат будет true, а для 128 уже false. Все дело в статичном методе valueOf() который вызывается при инициализации переменной. Этот метод, как раз оптимизирует количество объектов в памяти, используя IntegerCache, и достаёт уже ранее созданные объекты из памяти если они есть. Как раз это и есть пример использования паттерна Flyweight в реальном мире. Тоже самое касается и StringPool, ShortCache, LongCache, CharacterCache
Шаги реализации
- Разделите поля класса, который станет легковесом, на две части:
- внутреннее состояние: значения этих полей одинаковы для большого числа объектов;
- внешнее состояние (контекст): значения полей уникальны для каждого объекта.
2. Оставьте поля внутреннего состояния в классе, но убедитесь, что их значения неизменяемы. Эти поля должны инициализироваться только через конструктор.
3. Превратите поля внешнего состояния в параметры методов, где эти поля использовались. Затем удалите поля из класса.
4. Создайте фабрику, которая будет кешировать и повторно отдавать уже созданные объекты. Клиент должен запрашивать из этой фабрики легковеса с определённым внутренним состоянием, а не создавать его напрямую.
5. Клиент должен хранить или вычислять значения внешнего состояния (контекст) и передавать его в методы объекта легковеса.
Преимущества и недостатки
Плюсы
Минусы
- Усложняет код программы из-за введения множества дополнительных классов.
- Расходует процессорное время на поиск/вычисление контекста.
Ну и что?
Итак, мы выяснили, что паттерн Легковес может использоваться при разработке мобильных приложений под Android OS для экономии памяти путем выделения общего состояния, не выделяя при этом память под каждый одинаковый объект. Как видите в Java этот паттерн тоже активно используется, и теперь вы сможете ответить на вопрос на собеседовании, что будет при сравнении двух чисел 127.
Пример проекта
Понравилась статья? Не забудь подписаться и поставить лайк статье, а ещё
Источник